You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This PR introduces Mapped Types, a new kind of object type that maps a type representing property names over a property declaration template. In combination with index types and indexed access types (#11929), mapped types enable a number of interesting and useful type transformations. In particular, mapped types enable more accurate typing of intrinsic functions such as Object.assign and Object.freeze as well as APIs that map or transform shapes of objects.
where P is an identifier, K is a type that must be assignable to string, and T is some type that can use P as a type parameter. A mapped type resolves to an object type with a set of properties constructed by introducing a type parameter P and iterating it over the constituent types in K, for each such P declaring a property or index signature with the type given by T (which possibly references P as a type parameter). When P is a string literal type, a property with that name is introduced. Otherwise, when P is type string, an index signature is introduced.
Type relationships involving mapped types are described in #12351. For information on type inference involving mapped types, see #12528 and #12589. For information on preservation of property modifiers with mapped types, see #12563.
The following four mapped types are predefined in lib.d.ts as of #12276:
// Make all properties in T optionaltypePartial<T>={[PinkeyofT]?: T[P];};// Make all properties in T readonlytypeReadonly<T>={readonly[PinkeyofT]: T[P];};// From T pick a set of properties KtypePick<T,KextendskeyofT>={[PinK]: T[P];}// Construct a type with a set of properties K of type TtypeRecord<Kextendsstring,T>={[PinK]: T;}
interfaceShape{name: string;width: number;height: number;visible: boolean;}functionf1(s1: Shape,s2: Shape){assign(s1,{name: "circle"});assign(s2,{width: 10,height: 20});}functionf2(shape: Shape){constfrozen=freeze(shape);frozen.name="circle";// Error, name is read-only}functionf3(shape: Shape){constx=pick(shape,"name","visible");// { name: string, visible: boolean }}functionf4(){constrec={foo: "hello",bar: "world",baz: "bye"};constlengths=mapObject(rec,s=>s.length);// { foo: number, bar: number, baz: number }}
The mapObject example above shows how type inference can be used for mapped types. When inferring from an object type S to a mapped type { [P in K]: T }, keyof S is inferred for K and S[keyof S] is inferred for T. In other words, a literal union type of all property names in S is inferred for K and a union of all property types in S is inferred for T.
Another common pattern:
// A proxy for a given typetypeProxy<T>={get(): T;set(value: T): void;}// Proxify all properties in TtypeProxify<T>={[PinkeyofT]: Proxy<T[P]>;}functionproxify<T>(obj: T): Proxify<T>{// Wrap proxies around properties of obj}functionf5(shape: Shape){constp=proxify(shape);letname=p.name.get();p.visible.set(false);}
This PR introduces Mapped Types, a new kind of object type that maps a type representing property names over a property declaration template. In combination with index types and indexed access types (#11929), mapped types enable a number of interesting and useful type transformations. In particular, mapped types enable more accurate typing of intrinsic functions such as
Object.assignandObject.freezeas well as APIs that map or transform shapes of objects.A mapped type takes one of the forms
where
Pis an identifier,Kis a type that must be assignable tostring, andTis some type that can usePas a type parameter. A mapped type resolves to an object type with a set of properties constructed by introducing a type parameterPand iterating it over the constituent types inK, for each suchPdeclaring a property or index signature with the type given byT(which possibly referencesPas a type parameter). WhenPis a string literal type, a property with that name is introduced. Otherwise, whenPis typestring, an index signature is introduced.Type relationships involving mapped types are described in #12351. For information on type inference involving mapped types, see #12528 and #12589. For information on preservation of property modifiers with mapped types, see #12563.
The following four mapped types are predefined in lib.d.ts as of #12276:
Some functions that use the above types:
And some code that uses the functions:
The
mapObjectexample above shows how type inference can be used for mapped types. When inferring from an object typeSto a mapped type{ [P in K]: T },keyof Sis inferred forKandS[keyof S]is inferred forT. In other words, a literal union type of all property names inSis inferred forKand a union of all property types inSis inferred forT.Another common pattern:
Related issues include #1295, #2710, #4889, #6613, #10725, #11100,