TypeScript: For `T extends M` where `M` is a mapped type, `T[keyof T]` doesn't consider `M`
TypeScript Version: 3.4.0-dev.201xxxxx and 3.3.3333 (used to work in TS 3.2)
Search Terms: Mapped type, T[keyof T]
Code
// Takes type -> {a: string}
// returns type -> {a: string | null}
type Nullable<T extends object> = {
[P in keyof T]: T[P] | null;
};
// This function should only accept objects, such that all props can be assigned null.
function f<T extends Nullable<T>>(t: T, key: keyof T) {
let x = t[key];
x = null;
}
Expected behavior:
x = null to be accepted as T’s lower type bound is Nullable<_> thus all properties have | null.
Actual behavior: This was accepted up to TS 3.2, but started erring with TS 3.3 with the error:
ERROR(11,3): : Type 'null' is not assignable to type 'T[keyof T]'.
** Some notes **
There is nothing special about Nullable, same error happens with other mapped types.
This is not my code and there is a valid question why even bother writing f as written, since TS accepts:
let x: {a: string} = {a: ''};
f(x, 'a');
I.e. the Nullable lower bound doesn’t seem to be checked at the call-site.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 1
- Comments: 15 (11 by maintainers)
Probably, yeah. @rikov isn’t this the much simpler way to write that?:
as written, that
setValuecan be invoked with type params which would make that assignment unsound, eg: