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.
CodePudding user response:
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]}
CodePudding user response:
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'
};