Repository navigation
Distinguish missing and undefined object properties. - #30796
Jack Williams (jack-williams) wants to merge 10 commits into
Conversation
|
So a couple of observations after playing whack-a-mole with I think this change should come paired with some utility package to transform all existing properties: { foo?: Type } ~~~> { foo?: Type | undefined } // if undefined not in TypeIn theory this should be semantics preserving and allow people to just 'upgrade' without deciding to spend a Saturday doing it manually like some idiots. I don't think this will catch many existing correctness bugs. In most cases the old behaviour was conservative and prevented anything bad happening. The existing mechanisms that can actually distinguish missing or undefined properties seem rarely used. This comes with a big caveat: I'm not someone that uses Where I think this change does shine is in preventing/understanding performance bugs that arise by messing up your object layouts. Assuming legacy properties have been transformed so that they look like: interface Foo {
x?: number | undefined;
}it is now a one character change to track down the places where you don't initialise x explicitly and produce a different shape. If you only have a single location where |
|
Do you plan to add a |
|
Jack Leigh (@leighman) As it stands, no I don't plan to. My reason is that conditional types only relate types but I don't claim ownership of this feature or PR, so don't take this as a statement of this is how the feature is going to be. This is just me saying: please don't wait for me to add this. |
|
Jack Leigh (@leighman) The missing type you’re looking for already exists in the form of |
|
ExE Boss (@ExE-Boss) I'm pretty sure interface X { field: never; }
const x: X = {};doesn't work. A type AllFieldsMissing<T> = {
missing [P in keyof T];
// or
//[P in keyof T]: missing;
};
type AllFieldsOrNone<T> = T | AllFieldsMissing<T>;
type MyType = MyBaseType & AllFieldsOrNone<ExtraFieldGroup>;
interface MyBaseType {
a: number;
b: string;
}
interface ExtraFieldGroup {
c: string;
d: 'some thing' | 'other thing';
e: number;
}I'm pretty sure this can't be implemented yet. |
|
This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise. |
Starts the ball rolling on #13195.
A couple of things to highlight:
I looked into distinguishing optional function arguments too, but I got buried under a mountain of errors in checker.ts. I limited this change to just object properties, which I think is far more useful.
There is some interesting behaviour with index access type now, because they type property access. For example:
So now
Bis not assignable toA, when it was before.