Typescript: Unable to specify 'if T is optional' in a conditional Type

Created on 3 Apr 2018  ·  5Comments  ·  Source: microsoft/TypeScript


TypeScript Version: 2.8.1


Search Terms:
condition types, unions, optional, undefined

Code

interface StringOption{
    type: "string";
}

interface NumberOption{
    type: "number";
}

interface ISampleObject {
    requiredParam: string,
    optionalParam?: number
}

type MappedOptions<T> = {
    readonly [P in keyof T]: T[P] extends undefined ? StringOption : NumberOption;
}

const mappedObject: MappedOptions<ISampleObject> = {
    requiredParam: {type: "number"},
    optionalParam: {type: "string"}
}

Expected behavior:

as optionalParam is optional you should be able to switch on that in conditional type so that when mapped optionalParam is of type StringOption and requiredParam is of type NumberOption.

Actual behavior:
both types are of type NumberOption as neither extend undefined. A syntax is needed to say that a type includes a type in a union I suppose and as far as I know this is not yet available.

Playground Link:
Playground link

Question

Most helpful comment

I'm looking for a way to create optional props conditionally, let's say, if prop A is defined make prop B optional, or if prop B is defined then prop A is optional, I'm wondering if this is the case of this solution and if so, how to use it?

All 5 comments

I guess you want undefined extends T[P] ? NumberOption : StringOption.

you can also remove the optionality later on using -?:

type MappedOptions<T> = {
    readonly [P in keyof T]-?: undefined extends T[P] ? NumberOption : StringOption
}

I was just about to reply and say that still doesn't work but string null checks wasn't turned on.

Now does exactly what I want. Thanks

Playground Link

export type OptionalPropertyNames<T> = {
    [K in keyof T]-?: undefined extends T[K] ? K : never
}[keyof T];
export type RequiredPropertyNames<T> = {
    [K in keyof T]-?: undefined extends T[K] ? never : K
}[keyof T];
export type OptionalProperties<T> = Pick<T, OptionalPropertyNames<T>>
export type RequiredProperties<T> = Pick<T, RequiredPropertyNames<T>>

I arrived looking for these, and was able to piece it together based on the great information above.

Should undefined extends work outside mapped types? See here

edit: Nevermind, looks like this was fixed in 3.1.0

I'm looking for a way to create optional props conditionally, let's say, if prop A is defined make prop B optional, or if prop B is defined then prop A is optional, I'm wondering if this is the case of this solution and if so, how to use it?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DanielRosenwasser picture DanielRosenwasser  ·  3Comments

wmaurer picture wmaurer  ·  3Comments

weswigham picture weswigham  ·  3Comments

fwanicka picture fwanicka  ·  3Comments

bgrieder picture bgrieder  ·  3Comments