CommonJS interop
#19675
-
Let's call this esModuleInterop.
-
This PR gives people the Babel behavior that synthesizes a namespace with a default export with plucked properties.
- We want people to actually use this because it gives people a migration path to using Node's interop scheme for ES modules.
-
One change: allowSyntheticDefaultExports no longer actually allows you to default-import from .ts and .js files where inappropriate. Only from .d.ts files.
-
What about calling and constructing namespace imports?
import * as express from "express"
express();
- When using this flag, this will break; otherwise, users will get the same behavior.
-
Do we want to introduce an error?
- That's considered breaking for most people.
-
But we want to push people to use best practices.
- Put it as a default in
tsc --init.
-
Also, if a .d.ts file has a variable named __esModule, then we do the "right" thing.
- Should we start emitting
__esModule in .d.ts files?
- Seems arguable based on the output and the intent.
Comparability Relationship Adjustment
#19587
#19322
#19926
- The comparability relationship is somewhat limited in what it can express.
- Original differences between comparability are with union source types and optionality.
const x1 = { a: 1 as 1, b: "abc" };
const x2 = { a: 1, b: "abc" as "abc" };
if (x1 === x2) {
// ~~~~~~~~~
// Error
}
interface T1 { x: number }
interface T2 { y: number }
let x = { x: 100, y: 200 } as T1
let y = { x: 100, y: 200 } as T2
if (x === y) {
// ~~~~~~~
// Error
}
function f<T extends { a: number }, U>(x: T, y: U, z: { a: number}) {
// All of these are allowed...
let o = {};
z === {};
x === {};
o === {};
o === y;
x === { a: 42 }
// but not this...
x === y;
// ~~~~~~~
// Error!
}
- These are incomparable - we don't go bidirectionally on the
a property nor the b property.
- We only check both ways at the top level.
- Other issues: seems arguable whether
never should be comparable to/from anything apart from never.
- Perhaps we want to change comparability to only concern itself when things are potentially true.
- Only disallow when a comparison could never occur.
- Primitives/literal types are comparable to/from their base primitive "family" type.
- When comparing two object types, only check for properties present in both.
- We speculated about this when we first did comparable; do people actually run into this a lot?
- Well it's not unsound.
- Could you compare a function to an array?
- If you want to do this, it seems like you want to give users a way to say "no, this type is really not the type"
- Sounds like we need two type relationships: comparable and castable.
- It also feels kind of weird that in the true branch, you can't even assign one to the other after the fact.
- Should we just stop applying checks entirely around type assertions?
- Conclusion:
- Original use case should still be fixed - base primitive types & enum types are always comparable to/from their literal type.
- Hold off on the other changes.
CommonJS interop
#19675
Let's call this
esModuleInterop.This PR gives people the Babel behavior that synthesizes a namespace with a default export with plucked properties.
One change:
allowSyntheticDefaultExportsno longer actually allows you to default-import from.tsand.jsfiles where inappropriate. Only from.d.tsfiles.What about calling and constructing namespace imports?
Do we want to introduce an error?
But we want to push people to use best practices.
tsc --init.Also, if a
.d.tsfile has a variable named__esModule, then we do the "right" thing.__esModulein.d.tsfiles?Comparability Relationship Adjustment
#19587
#19322
#19926
aproperty nor thebproperty.nevershould be comparable to/from anything apart fromnever.