Closed
Description
Contextually Typed and Satisfies Operator
#47920
https://github.com/microsoft/TypeScript/pull/47898/files
- Looked through use-cases.
- Safe type assertion
- Want something like
as
but safe - so a safe type assertion. - Often needed due to control flow limitations (Trade-offs in Control Flow Analysis #9998)
- Want something like
- Property name constraints
- "these properties may exist"
- Property name fulfillment
- "these properties must be present"
- Property value conformance
- "these properties must have the right types"
- Ensure interface implementation
- "I don't care about excess properties, but this has to satisfy this interface"
- Optional Member Conformance
- "The values conform to this type, but I want to hold on to the original type"
- ...
- More - check the issue
- Safe type assertion
- Excess property checks?
- Seems like you can just issue them by default and a user can intersect with
Record<string, unknown>
to opt out.someExpression satisfies SomeType & Record<string, unknown>
- Could go the other way to achieve excess property checks by intersecting with
Record<string, never>
- But excess property checks are part of the assignability relationship anyway. We don't want a second check.
- Seems like you can just issue them by default and a user can intersect with
- Aside, maybe safe upcast could be achieved with
x satisfies T as T
- Empty arrays!
- We infer
never[]
a lot of the time, which is useless. - Experiment with contextually typing array literals.
- We infer
- Syntax side?
satisfies
?extends
? We use that for type parameters that must be assignable to a constraint.implements
is what we use for classes - also closer in intuition- But also both of
- Reuse
as
syntax likeas const
?- Would be nice because we could reuse JSDoc cast syntax.
is
? Could conflict with pattern matching.- Marker type?
expr as Satisfies<T>
- Are we satisfied?
- 🙄
Definite Assignment Checks for Computed Keys
- Seems like this is broader than the issue described.
-
Yes, we will now narrow any element access reference.
const sym = Symbol(); declare let x: { [sym]: number | string; }; if (typeof x[sym] === "number") { let a = x[sym]; // 'number | string' today, 'number' with this PR }
-
- We like this, but this is more work for every program, not just restricted to classes.
- It's a relatively small slowdown, but every slowdown adds up over a few releases.
- Want to get more eyes on this so we feel comfortable with the change.