Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to specify 'if T is optional' in a conditional Type #23126

Closed
Roaders opened this issue Apr 3, 2018 · 7 comments
Closed

Unable to specify 'if T is optional' in a conditional Type #23126

Roaders opened this issue Apr 3, 2018 · 7 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@Roaders
Copy link

Roaders commented Apr 3, 2018

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

@mhegazy
Copy link
Contributor

mhegazy commented Apr 3, 2018

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
}

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Apr 3, 2018
@Roaders
Copy link
Author

Roaders commented Apr 4, 2018

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

@Roaders Roaders closed this as completed Apr 4, 2018
@fcrick
Copy link

fcrick commented Jun 9, 2018

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.

@aleclarson
Copy link

aleclarson commented Sep 24, 2018

Should undefined extends work outside mapped types? See here

edit: Nevermind, looks like this was fixed in 3.1.0

@samuelcastro
Copy link

samuelcastro commented Jan 24, 2019

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?

@JamesJansson
Copy link

Thank you @aleclarson, testing whether a parameter is optional works well using
undefined extends T
which can be used in a generic tuple quite nicely.

@jpitchardu
Copy link

jpitchardu commented Aug 12, 2022

Hi, I'm trying to find any docs on -? but I haven't been able to, does anybody know where to find them? Thanks

##Edit

Found this PR #21919

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

7 participants