TypeScript Version: 3.3.3333
Search Terms: NonPartial, remove optional modifier
Code
// A *self-contained* demonstration of the problem follows...
// Test this by running `tsc` on the command-line, rather than through another build tool such as Gulp, Webpack, etc.
interface OptClass {
opt?: number;
}
type NonPartialIsh = {[K in keyof OptClass]-?: OptClass[K] | undefined};
const test = {opt: undefined};
verify<NonPartialIsh>(test); // should NOT be error, but shows error
function verify<T>(a: T) {}
Expected behavior:
NonPartialish.opt type should support undefined.Actual behavior:
ERROR(12,23): : Argument of type '{ opt: undefined; }' is not assignable to parameter of type 'NonPartialIsh'.
Types of property 'opt' are incompatible.
Type 'undefined' is not assignable to type 'number'.
Transpiled code follows despite errors.
NonPartialish.opt type does not support undefined.Playground Link: https://www.typescriptlang.org/play/#src=%2F%2F%20A%20self-contained%20demonstration%20of%20the%20problem%20follows...%0D%0A%2F%2F%20Test%20this%20by%20running%20%60tsc%60%20on%20the%20command-line%2C%20rather%20than%20through%20another%20build%20tool%20such%20as%20Gulp%2C%20Webpack%2C%20etc.%0D%0A%0D%0Ainterface%20OptClass%20%7B%0D%0A%20%20opt%3F%3A%20number%3B%0D%0A%7D%0D%0A%0D%0Atype%20NonPartialIsh%20%3D%20%7B%5BK%20in%20keyof%20OptClass%5D-%3F%3A%20OptClass%5BK%5D%20%7C%20undefined%7D%3B%0D%0A%0D%0Aconst%20test%20%3D%20%7Bopt%3A%20undefined%7D%3B%0D%0A%0D%0Averify%3CNonPartialIsh%3E(test)%3B%20%20%2F%2F%20should%20NOT%20be%20error%2C%20but%20shows%20error%0D%0A%0D%0Afunction%20verify%3CT%3E(a%3A%20T)%20%7B%20%7D%0D%0A
Related Issues:
I believe -? removes undefined intentionally, because ? adds it.
Optional and undefined are two different things. Optional adds undefined which is expected.
But removing Optional shouldn't remove explicitly typed undefined (by union).
Unfortunately missing and undefined aren't consistently two different things in TypeScript; see #13195.
Relevant documentation on the behavior of -?:
Note that in
--strictNullChecksmode, when a homomorphic mapped type removes a?modifier from a property in the underlying type it also removesundefinedfrom the type of that property
But in
{[K in keyof T]-?: Foo<T[K]>}
should undefined be excluded from the original type of the property (T[K]) or the mapped type of the property (Foo<T[K]>)? I'd kind of expect it to be the former but it looks like it's actually the latter.
Assuming we can't destabilize the current behavior, someone who wants to strip the optional modifier off property keys but hold on to undefined in their values could do so by preventing the compiler from recognizing the mapped type as homomorphic:
type NullablyRequired<T> = { [P in (keyof T & keyof any)]: T[P] }
type Test = NullablyRequired<{a?: string, b: number}>
// type Test = {a: string | undefined, b: number}
@weswigham I think it should at least work when you explicitly declare undefined to be a valid value, but it doesn't.
interface OptClass {
opt?: number | undefined;
}
Wow had no idea there's -?... is there a way to remove | undefined somehow - so that something like string | undefined would become simply string?
Most helpful comment
Unfortunately missing and undefined aren't consistently two different things in TypeScript; see #13195.
Relevant documentation on the behavior of
-?:But in
should
undefinedbe excluded from the original type of the property (T[K]) or the mapped type of the property (Foo<T[K]>)? I'd kind of expect it to be the former but it looks like it's actually the latter.Assuming we can't destabilize the current behavior, someone who wants to strip the optional modifier off property keys but hold on to
undefinedin their values could do so by preventing the compiler from recognizing the mapped type as homomorphic: