Reputation: 5691
Is it possible to create Typescript Type based on object that modifies its keys?
For example this is the thing I would like to achieve:
const super: SuperType<{getData: any}> = ...
super.getDataEXTENSION (Note it should have this modified key)
I know we can define
type ModifiedName<T extends string> = `${Capitalize<T>}EXTENSION`;
type GetObjectWithModifiedPropertyNames<T extends any> = {
[key in keyof T]: any;
};
but calculating the keys is problematic:
type GetObjectWithModifiedPropertyNames<T extends any> = {
[key: ModifiedName<keyof T>]: any;
};
I know it is possible to modify return type, arguments etc but regarding modifying the keys I am not sure it is possible.
Upvotes: 0
Views: 107
Reputation: 20589
You can use TypeScript's conditional type syntax to only allow keys that are type of string. The following will define ModifiedName as the Capitalized key + EXTENSION only if key it extends string. Otherwise the key will not be used in the type since the false response of the condition is never.
type ModifiedName<T extends string | number | Symbol> =
`${ T extends string ? Capitalize<T> : never }EXTENSION`;
type GetObjectWithModifiedPropertyNames<T> = {
[key in ModifiedName<keyof T>]: any;
};
Here's an example of shows a valid usage scenario. It will not expect 1EXTENSION to be a key, and adding a property of ['1EXTENSION']
would result in an error.
interface Foo {
abc: number;
efg: string;
1: string;
}
let obj: GetObjectWithModifiedPropertyNames<Foo> = {
AbcEXTENSION: 'hi',
EfgEXTENSION: 'avc'
};
Upvotes: 2
Reputation: 51093
You can use the as
syntax in a mapped type:
type ModifiedName<T extends string> = `${Capitalize<T>}EXTENSION`
type Foo = {foo: string, bar: number}
// type ModifiedFoo = {FooEXTENSION: string, BarEXTENSION: number}
type ModifiedFoo = {[K in keyof Foo as ModifiedName<K>]: Foo[K]}
Upvotes: 2