Closed
Description
satisfies
Operator
- Most recent change involves the contextual type of the expression being the intersection of the outer contextual type and the type being checked for satisfaction.
- Have to be careful - there are places where we don't always create intersections because it's not always desirable to do this.
instanceof
might do something similar here?
- Intersections? For things with methods? That will produce overload methods?
-
That can lead to a "bad" contextual type occasionally.
-
Especially generic methods (e.g. array methods)
interface Movable1 { move<U>(distance: U, b: boolean): void; } interface Movable2 { move<T, U>(distance: T, b: boolean): void; } const danger: Movable1 & Movable2 = { move(s) { } }
-
- Do you always want to use the satisfies type before the outer type?
- We sort of do something like this for destructuring.
- How does this work for nested
satisfies
?- "I want to satisfy these three interfaces?"
- Do these stack? How?
- Is this like
implements
?- Why aren't we doing
implements
again? - Possible future ECMAScript proposals.
- Why aren't we doing
- Inside-to-outside seems pretty intuitive for a lot of usage.
- We really don't want to create a new typing context.
- Why did we need to try the intersection type?
- Feels like many of these cases are motivated by index signatures.
extends
on infer
in Conditional Types
- When we see a
?
after anextends SomeType
, we always have to assume that we're about to start parsing a conditional type on the right. - We do look-ahead, and we also need to intentionally parenthesize these cases.
- Basically "if there's a question mark following, then you're parsing a conditional type, not
- Is this just for template literals?
- No, lots of stuff where we have to have nested conditional types to test on an extracted type.
- Seems reasonable.
Inferring More Specific Types for Template Constraints
- Want to be able to parse out round-trippable JS strings.
- Added some logic to do this, and can take advantage with implicit bounds with a type helper called
Is
type Is<T extends U, U> = T
, withIs<infer T, number>
- Presumably most users will leverage Add 'extends' clause to 'infer' type #48112.
- Prioritized list - if you have a type variable bounded by
number | bigint
, first try to parse outnumber
. If that isn't round-trippable, try to parse outbigint
.
Contextually Typing Boolean Literals
type Box<T> = {
get: () => T;
set: (x: T) => void;
};
declare function box<T>(x: T): Box<T>;
// okay, Box<number>
const a = box(0);
// okay, Box<number>, `0` gets contextually typed but doesn't make a difference.
const b: Box<number> = box(0);
// okay, Box<boolean>
const c = box(false);
// error!?
// `false` gets contextually typed by `boolean` which is `true | false`
// which makes the type of the extression `false` be the type `false`.
// That means we try to see if the type `Box<false>` is assignable to `Box<boolean>`,
// and it's not because `Box` is assignability is invariant on `T`.
const d: Box<boolean> = box(false);
- First idea (Widen boolean literals when contextual type is full boolean type #48368): if you're contextually typed by both
true
andfalse
, then widen toboolean
.- But you can be contextually typed by
boolean
because types of properties merge.
- But you can be contextually typed by
- New idea - if we get a
boolean
inference from a return type, remove it from the instantiated contextual type, remove it. - Very narrow fix for just
boolean
s - but doesn't work for other types. For example,const x: Box<0 | 1> = box(0)
.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment