Closed
Description
Infer Template Literal Types from Template Expressions
- Up until this PR, whenever you'd write a template literal expression, we'd just infer
string
. - With this PR, we always give a template literal type to these expressions.
- We now have a widening and non-widening form.
- Non-widening form is "fresh", widens to string once it flows into a mutable location.
- So
const
preserves the literal-ness, whilelet
enforces a widening
- Weird issue - template literal types didn't consistently have a string constraint, so werent assignable to other top-level types.
- Side note: don't waste time on Node 8.
- If you infer
`hello${string}world`
from`hello${foo}world`
, does that mean you're expecting at least one character in the middle?- No, only applies to consecutive generics with no delimiter, e.g.
`hello${T}${U}world`
whereT
andU
both extendstring
.
- No, only applies to consecutive generics with no delimiter, e.g.
- This is a breaking change because we used to always widen the results of a function to return
string
. - In the return type of a function, we return the non-widening variant, right?
- Correct.
Optional Property Checking Against Index Signatures
-
When we have spreads with optional properties, we don't correctly mix in
undefined
.declare let r: { [key: string]: number }; declare let fromAnnotation: { x?: number }; r = { ...fromAnnotation }; // Error: Type 'undefined' is not assignable to type 'number'. let fromExpression = { ...!!true ? { x: 3 } : {} }; r = { ...fromExpression }; // Ok
-
Also discussed allowing properties with
undefined
to be assignable to an index signature.- Likely can't truly fix index signatures to always implicitly produce
undefined
because of arrays. - We could do this just for string index signatures.
- Likely can't truly fix index signatures to always implicitly produce
-
With the string index signature behavior permitting
undefined
properties, how does this extend to our "generalized key types"?- Would imagine that it does extend correctly.
-
What about
delete
? -
What's the mechanism for this? Some higher-order thing?
- No, strip out
undefined
from the property before the check.
- No, strip out
-
Is it weird to make an exception for numeric index signatures?
-
Probably doesn't matter.
-
Totally matters
const tuple = [undefined, 2, 3] as const; var arr: number[] = tuple; // make sure this still errors
-
-
Is there a way to track whether these were optional to begin with? And only do the check then?
-
A more limited change, and you can't take back the behavior as easily if you always allow
undefined
.declare let fromAnnotation2: { x: number | undefined }; // Error: Type 'undefined' is not assignable to type 'number'. declare let r: { [key: string]: number } = { ...fromAnnotation2 };
-
-
Conclusion: try this with just optional properties.
- The magic happens in
indexTypesRelatedTo
witheachPropertyRelatedTo
.
- The magic happens in
Option to Use unknown in try
/catch
Variable Types
- Why is it not a strict flag?
- It's not, but it could be.
- Feel like taking a slower approach on this is okay.
- But that's the point of
strict
, getting better checks, right? - If you have
noImplicitAny
, is that an error today?- Probably good support for the idea that this should be a
strict
mode flag.
- Probably good support for the idea that this should be a
- Maybe this should just be under
noImplicitAny
. - The philosophy of
strict
is being open to being broken as soon as we get better. - Gaping hole in the product that nobody has really paid attention to.
- Maybe we should have an easy
: any
quick fix. - Conclusion
- Workshop name
- See what breaks under
strict
- Quick fix
Remove Special any
Assignability Exception from Numeric Index Signatures
- How did it make sense before?
- Well, it sorta didn't.
- Numeric index signatures are supposed to map a subset of string properties.
- This breaks transitivity.
- Wait, no, it's fine.
- Hearkens back to the "dense vs. sparse" conversation in the first topic.
- Having no numeric properties means that you should be compatible technically!
- In line with the original change.
- What breaks?
- Test based on Mithril
- Office UI Fabric
- RxJS (but in a good way)
- Anecdote: we have a tendency to say "oh my gosh, what's a user supposed to do?", but when outside the team, we would take the time to fix correctness issues and we'd be better off doing it.
- Historically, with issues like this, how helpful have we found the release notes to be helpful?
- Mixed bag, but it does help a lot of people.
- Original scenario is compelling; what about an alternative approach.
- Implemented
object
type a while back - might want to create afunction
type?- Opposite use-case, doesn't help here.
- Conclusion: evaluate what the fixes feel like on the codebase.