Closed
Description
Lazily Compute Module Shapes/APIs in --incremental
- When we are emitting all files under
--watch
, we generate a.tsbuildinfo
file. - Idea is, don't generate the
.d.ts
emit for a file the first time. - Only when a single file changes, that's when we'll compute the change.
- But when we have
composite
, we'll still have to do the.d.ts
emit.- So, unclear if this is what you want for
composite
.
- So, unclear if this is what you want for
- The first change in any file will be unpredictable.
- Aside: do we need to hash
.d.ts
emit?- We could come up with an alternative - but
.d.ts
is convenient.
- We could come up with an alternative - but
- So you have to do more work on the subsequent change?
- Well, you're moving it to later.
- Kind of amortizing it.
- So with the
composite
flag, ideally we'd want to reuse the.d.ts
files since you're redoing all the same work.- Is that possible?
- If you're using this for just type-checking with
--noEmit
, the up-front benefit is great. - When do you lose?
tsc --watch
, read the news, make a change, and a re-check is not that fast.- Is that compelling enough for a flag?
- Seems like no, nobody feels strongly enough.
- We want the change, need to review it.
assumeChangesAffectShape
for --incremental
and --watch
scenarios
- If you don't have
.d.ts
emit enabled, you have to still pay for the cost of.d.ts
emit. - Idea: instead of consulting your
.d.ts
files, every change impacts your dependencies. - Can we test with existing teams?
- They likely already have
.d.ts
emit, not ideal
- They likely already have
- Let's revisit.
Re-relax Index Signature Requirements
- Really, we're expanding the checks to cover 2 new cases.
- ✅
SomeObject -> { [x: string]: any }
- ✅
SomeObject -> { [x: string]: any, [x: number]: any }
- ✅
- Doesn't work for intersections of like
{ [x: string]: any } & { [x: number]: any }
- kind of esoteric though. - No objections - looking for code review.
Experiments in Narrowing Generics
interface A {
a: number | null;
}
function get<T, K extends keyof T>(obj: T, key: K) {
let p = obj[key];
if (p !== null) {
let x: number = p; // doesn't narrow!
}
}
- Want to be able to say when a type variable has a constraint, you want to lift that constraint up to an intersection of the type variable and its constraint.
-
T extends "a" | "b"
- ->
T & ("a" | "b")
- ->
T & "a" | T & "b"
.
-
- Once you do that, you can narrow those intersections with
x === "a"
andx === "b"
accordingly. - Reminds some of us of negated types.
- With negated types, we had perf problems of generating a ton of types.
- What about a constraint of
IntrinsicElements
or something? - Is this something where we could have a size limit?
- What about a constraint of
- Will this introduce a lot of subtype reduction?
- Think most code will have no effect at all?
- If we could make this efficient, could we do negated types?
- That's not why we didn't do negated types.
- "Yeah, but that's why I stopped bringing them up"
- 🤨
- Do we manufacture these unions of intersection lazily?
- Unclear - sounds like yes?