Description
Consider the following hierarchy:
interface Base {
kind: string;
}
interface Derived1 extends Base {
prop1: number;
}
interface Derived2 extends Base {
prop2: string;
}
interface Container {
a: Base;
}
let x: Container = {
a: {
kind: "Derived1",
prop1: 1000,
}
}
Humor the idea that when Container
says that it has a property a
, there was an implicit setof types that will be accounted for throughout the program - Derived1
and Derived2
. Really, a
should have type Derived1 | Derived2
, but there's is an intuition of doing things with a common supertype from languages like C#, Java, etc. The above code is perfectly valid, however, in 1.6 we will report:
foo.ts(17,5): error TS2322: Type '{ a: { kind: string; prop1: number; }; }' is not assignable to type 'Container'.
Types of property 'a' are incompatible.
Type '{ kind: string; prop1: number; }' is not assignable to type 'Base'.
Object literal may only specify known properties, and 'prop1' does not exist in type 'Base'.
I think the consequences of this were recognized, but underestimated. For instance, as part of my work for #4081, I've run into a test case where I have 177,000 lines of tests that utilized this pattern - see fhir/fhir-tests.d.ts.
Do we feel we can think of a better way for users to deal with this? There's no way users are willing to comb through that much code and add type assertions to fix that test. I know the definitions could be amended to use string index signatures, but that gets us back to square 1 (plus, there's 10K lines in the definition file as well.