Home > Software design >  In typescript Can I map a type to have ? on property when its corresponding value satisfies a certai
In typescript Can I map a type to have ? on property when its corresponding value satisfies a certai

Time:02-28

For example, given an object:

const TypeDef1 = {
    foo: {optional: true, type: 'string'},
    bar: {type: 'number'}
}

which conforms to type, say

type TypeDef = {
    [key: string]: {
        optional?: boolean,
        type: 'number' | 'string' | 'boolean'
    }
}

I want to have some reusable typing Transform<T extends TypeDef> such that

Transform<typeof TypeDef1>

gives:

{
    foo?: string
    bar: number
}

Is this at all possible in Typescript?

CodePudding user response:

You can use a combination of mapped and conditional types to transform the type definition to an actual type (provided we also use an as const assertion on the definition to make sure we preserve all type info.


type TypeDef =  { [key: string]: { optional?: boolean, type: 'number' | 'string' | 'boolean' } };
type TypeNameToType = {
    number: number,
    string: string,
    boolean: boolean
}
type TypeDefToType<T extends TypeDef> = {
    // The optional properties
    -readonly [P in keyof T as T[P]['optional'] extends true ? P: never]?: TypeNameToType[T[P]['type']]
} & {
    // The mandatory properties
    -readonly [P in keyof T as T[P]['optional'] extends true ? never: P]: TypeNameToType[T[P]['type']]
}

const TypeDef1 = {
    foo: {optional: true, type: 'string'},
    bar: {type: 'number'}
} as const


type X = TypeDefToType<typeof TypeDef1>
//   ^?
// type X = {
//     foo?: string | undefined;
// } & {
//     bar: number;
// }

Playground Link

  • Related