I have an interface User
:
interface User {
_id : string;
name : string;
email : string;
password: string;
phone : number;
}
I have another interface UpdatedBy
:
interface UpdatedUser {
id : string;
name: string;
}
I know I can use Pick
, but I want to rename _id
to id
in the UpdatedUser
interface.
type UpdatedUser = Pick<User, '_id' | 'name'>; // How can I turn _id into id?
Update: I basically want to do a cleaner version of this:
export interface UpdatedUser extends Pick<User, 'name'> {
id : Extract<User, '_id'>;
}
Syntax: obj['New key'] = obj['old key']; Note: Renaming the object by simple assignment of variable could be applied on multiple key, value pairs.
Add a typescript property. Select it and press F2 (or right click and select rename from the menu)
To rename a key in an object:Use bracket notation to assign the value of the old key to the new key. Use the delete operator to delete the old key. The object will contain only the key with the new name.
keyof is a keyword in TypeScript which is used to extract the key type from an object type.
There is no built-in type for a renaming Pick
, fortunately we can create one with reasonable effort.
type IdRenamed = Omit<User, "_id"> & { id: User["_id"] }
// { name: string; email: string; password: string; phone: number; id: string;}
Playground
type PickRename<T, K extends keyof T, R extends PropertyKey> =
Omit<T, K> & { [P in R]: T[K] }
type T21 = PickRename<User, "_id", "id"> // same type as above
type T22 = PickRename<User, "foo", "id"> // error, foo is no property
Playground
TS 4.1 Alternative: use mapped type as
clauses. Its advantage is that readonly
or optional (?
) modifiers of properties are preserved (see homomorphic mapped types 1, 2 for more details).
type PickRename<T, K extends keyof T, R extends PropertyKey> = {
[P in keyof T as P extends K ? R : P]: T[P]
} // type instantiation same as previous example
Playground
type PickRenameMulti<T, R extends
{ [K in keyof R]: K extends keyof T ? PropertyKey : "Error: key not in T" }
> = Omit<T, keyof R> & UnionToIntersection<
{ [P in keyof R & keyof T]: { [PP in R[P]]: T[P] } }[keyof R & keyof T]
>
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends
((k: infer I) => void) ? I : never
type T31 = PickRenameMulti<User, { _id: "id"; name: "firstName" }>
type T32 = PickRenameMulti<User, { foo: "id" }> // error, foo is no property
Note: See the great UnionToIntersection
type for more details on the helper.
Playground
TS 4.1 again eases up syntax and produces homomorphic mapped types:type PickRenameMulti<T, R extends
{ [K in keyof R]: K extends keyof T ? PropertyKey : "Error: key not in T" }
> = { [P in keyof T as P extends keyof R ? R[P] : P]: T[P] }
Playground
_
prefix from all property keystype DropUnderscore<T> = {
[K in keyof T as K extends `_${infer I }` ? I : K]: T[K]
};
type T4 = DropUnderscore<User> // "_id" and "_email" renamed to "id", "email"
Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With