Compute writeType from set accessors for union and intersection properties (#47674)

* Compute write type from set accessors for union and intersection properties

* Add test for deferred writeType

* Always check for writeType of symbol
This commit is contained in:
Andrew Branch
2022-02-08 12:57:34 -08:00
committed by GitHub
parent 17b97ccc43
commit c5b1011e94
17 changed files with 1105 additions and 1 deletions
+45 -1
View File
@@ -9696,6 +9696,41 @@ namespace ts {
return links.type;
}
function getWriteTypeOfSymbolWithDeferredType(symbol: Symbol): Type | undefined {
const links = getSymbolLinks(symbol);
if (!links.writeType && links.deferralWriteConstituents) {
Debug.assertIsDefined(links.deferralParent);
Debug.assertIsDefined(links.deferralConstituents);
links.writeType = links.deferralParent.flags & TypeFlags.Union ? getUnionType(links.deferralWriteConstituents) : getIntersectionType(links.deferralWriteConstituents);
}
return links.writeType;
}
/**
* Distinct write types come only from set accessors, but union and intersection
* properties deriving from set accessors will either pre-compute or defer the
* union or intersection of the writeTypes of their constituents. To account for
* this, we will assume that any deferred type or transient symbol may have a
* `writeType` (or a deferred write type ready to be computed) that should be
* used before looking for set accessor declarations.
*/
function getWriteTypeOfSymbol(symbol: Symbol): Type {
const checkFlags = getCheckFlags(symbol);
if (checkFlags & CheckFlags.DeferredType) {
const writeType = getWriteTypeOfSymbolWithDeferredType(symbol);
if (writeType) {
return writeType;
}
}
if (symbol.flags & SymbolFlags.Transient) {
const { writeType } = symbol as TransientSymbol;
if (writeType) {
return writeType;
}
}
return getSetAccessorTypeOfSymbol(symbol);
}
function getSetAccessorTypeOfSymbol(symbol: Symbol): Type {
if (symbol.flags & SymbolFlags.Accessor) {
const type = getTypeOfSetAccessor(symbol);
@@ -12198,6 +12233,7 @@ namespace ts {
let firstType: Type | undefined;
let nameType: Type | undefined;
const propTypes: Type[] = [];
let writeTypes: Type[] | undefined;
let firstValueDeclaration: Declaration | undefined;
let hasNonUniformValueDeclaration = false;
for (const prop of props) {
@@ -12213,6 +12249,10 @@ namespace ts {
firstType = type;
nameType = getSymbolLinks(prop).nameType;
}
const writeType = getWriteTypeOfSymbol(prop);
if (writeTypes || writeType !== type) {
writeTypes = append(!writeTypes ? propTypes.slice() : writeTypes, writeType);
}
else if (type !== firstType) {
checkFlags |= CheckFlags.HasNonUniformType;
}
@@ -12243,9 +12283,13 @@ namespace ts {
result.checkFlags |= CheckFlags.DeferredType;
result.deferralParent = containingType;
result.deferralConstituents = propTypes;
result.deferralWriteConstituents = writeTypes;
}
else {
result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes);
if (writeTypes) {
result.writeType = isUnion ? getUnionType(writeTypes) : getIntersectionType(writeTypes);
}
}
return result;
}
@@ -28509,7 +28553,7 @@ namespace ts {
return errorType;
}
propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : writing ? getSetAccessorTypeOfSymbol(prop) : getTypeOfSymbol(prop);
propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : writing ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop);
}
return getFlowTypeOfAccessExpression(node, prop, propType, right, checkMode);
+1
View File
@@ -4952,6 +4952,7 @@ namespace ts {
extendedContainersByFile?: ESMap<NodeId, Symbol[]>; // Containers (other than the parent) which this symbol is aliased in
variances?: VarianceFlags[]; // Alias symbol type argument variance cache
deferralConstituents?: Type[]; // Calculated list of constituents for a deferred type
deferralWriteConstituents?: Type[]; // Constituents of a deferred `writeType`
deferralParent?: Type; // Source union/intersection of a deferred type
cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target
typeOnlyDeclaration?: TypeOnlyAliasDeclaration | false; // First resolved alias declaration that makes the symbol only usable in type constructs
+4
View File
@@ -20,6 +20,10 @@ namespace ts {
return undefined;
}
export function getDeclarationsOfKind<T extends Declaration>(symbol: Symbol, kind: T["kind"]): T[] {
return filter(symbol.declarations || emptyArray, d => d.kind === kind) as T[];
}
export function createSymbolTable(symbols?: readonly Symbol[]): SymbolTable {
const result = new Map<__String, Symbol>();
if (symbols) {
@@ -0,0 +1,108 @@
//// [divergentAccessorsTypes3.ts]
class One {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
get prop2(): string { return ""; }
set prop2(s: string | number) { }
prop3: number;
get prop4(): string { return ""; }
set prop4(s: string | number) { }
}
class Two {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
get prop2(): string { return ""; }
set prop2(s: string) { }
get prop3(): string { return ""; }
set prop3(s: string | boolean) { }
get prop4(): string { return ""; }
set prop4(s: string | boolean) { }
}
declare const u1: One|Two;
u1.prop1 = 42;
u1.prop1 = "hello";
u1.prop2 = 42;
u1.prop2 = "hello";
u1.prop3 = 42;
u1.prop3 = "hello";
u1.prop3 = true;
u1.prop4 = 42;
u1.prop4 = "hello";
u1.prop4 = true;
//// [divergentAccessorsTypes3.js]
var One = /** @class */ (function () {
function One() {
}
Object.defineProperty(One.prototype, "prop1", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
Object.defineProperty(One.prototype, "prop2", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
Object.defineProperty(One.prototype, "prop4", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
return One;
}());
var Two = /** @class */ (function () {
function Two() {
}
Object.defineProperty(Two.prototype, "prop1", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
Object.defineProperty(Two.prototype, "prop2", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
Object.defineProperty(Two.prototype, "prop3", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
Object.defineProperty(Two.prototype, "prop4", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
return Two;
}());
u1.prop1 = 42;
u1.prop1 = "hello";
u1.prop2 = 42;
u1.prop2 = "hello";
u1.prop3 = 42;
u1.prop3 = "hello";
u1.prop3 = true;
u1.prop4 = 42;
u1.prop4 = "hello";
u1.prop4 = true;
@@ -0,0 +1,116 @@
=== tests/cases/compiler/divergentAccessorsTypes3.ts ===
class One {
>One : Symbol(One, Decl(divergentAccessorsTypes3.ts, 0, 0))
get prop1(): string { return ""; }
>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36))
set prop1(s: string | number) { }
>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 2, 12))
get prop2(): string { return ""; }
>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36))
set prop2(s: string | number) { }
>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 5, 12))
prop3: number;
>prop3 : Symbol(One.prop3, Decl(divergentAccessorsTypes3.ts, 5, 35))
get prop4(): string { return ""; }
>prop4 : Symbol(One.prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36))
set prop4(s: string | number) { }
>prop4 : Symbol(One.prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 10, 12))
}
class Two {
>Two : Symbol(Two, Decl(divergentAccessorsTypes3.ts, 11, 1))
get prop1(): string { return ""; }
>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36))
set prop1(s: string | number) { }
>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 15, 12))
get prop2(): string { return ""; }
>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36))
set prop2(s: string) { }
>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 18, 12))
get prop3(): string { return ""; }
>prop3 : Symbol(Two.prop3, Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36))
set prop3(s: string | boolean) { }
>prop3 : Symbol(Two.prop3, Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 21, 12))
get prop4(): string { return ""; }
>prop4 : Symbol(Two.prop4, Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36))
set prop4(s: string | boolean) { }
>prop4 : Symbol(Two.prop4, Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 24, 12))
}
declare const u1: One|Two;
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>One : Symbol(One, Decl(divergentAccessorsTypes3.ts, 0, 0))
>Two : Symbol(Two, Decl(divergentAccessorsTypes3.ts, 11, 1))
u1.prop1 = 42;
>u1.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36), Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36), Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36))
u1.prop1 = "hello";
>u1.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36), Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36), Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36))
u1.prop2 = 42;
>u1.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36), Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36), Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36))
u1.prop2 = "hello";
>u1.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36), Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36), Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36))
u1.prop3 = 42;
>u1.prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36))
u1.prop3 = "hello";
>u1.prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36))
u1.prop3 = true;
>u1.prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36))
u1.prop4 = 42;
>u1.prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36))
u1.prop4 = "hello";
>u1.prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36))
u1.prop4 = true;
>u1.prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36))
>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13))
>prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36))
@@ -0,0 +1,141 @@
=== tests/cases/compiler/divergentAccessorsTypes3.ts ===
class One {
>One : One
get prop1(): string { return ""; }
>prop1 : string
>"" : ""
set prop1(s: string | number) { }
>prop1 : string
>s : string | number
get prop2(): string { return ""; }
>prop2 : string
>"" : ""
set prop2(s: string | number) { }
>prop2 : string
>s : string | number
prop3: number;
>prop3 : number
get prop4(): string { return ""; }
>prop4 : string
>"" : ""
set prop4(s: string | number) { }
>prop4 : string
>s : string | number
}
class Two {
>Two : Two
get prop1(): string { return ""; }
>prop1 : string
>"" : ""
set prop1(s: string | number) { }
>prop1 : string
>s : string | number
get prop2(): string { return ""; }
>prop2 : string
>"" : ""
set prop2(s: string) { }
>prop2 : string
>s : string
get prop3(): string { return ""; }
>prop3 : string
>"" : ""
set prop3(s: string | boolean) { }
>prop3 : string
>s : string | boolean
get prop4(): string { return ""; }
>prop4 : string
>"" : ""
set prop4(s: string | boolean) { }
>prop4 : string
>s : string | boolean
}
declare const u1: One|Two;
>u1 : One | Two
u1.prop1 = 42;
>u1.prop1 = 42 : 42
>u1.prop1 : string | number
>u1 : One | Two
>prop1 : string | number
>42 : 42
u1.prop1 = "hello";
>u1.prop1 = "hello" : "hello"
>u1.prop1 : string | number
>u1 : One | Two
>prop1 : string | number
>"hello" : "hello"
u1.prop2 = 42;
>u1.prop2 = 42 : 42
>u1.prop2 : string | number
>u1 : One | Two
>prop2 : string | number
>42 : 42
u1.prop2 = "hello";
>u1.prop2 = "hello" : "hello"
>u1.prop2 : string | number
>u1 : One | Two
>prop2 : string | number
>"hello" : "hello"
u1.prop3 = 42;
>u1.prop3 = 42 : 42
>u1.prop3 : string | number | boolean
>u1 : One | Two
>prop3 : string | number | boolean
>42 : 42
u1.prop3 = "hello";
>u1.prop3 = "hello" : "hello"
>u1.prop3 : string | number | boolean
>u1 : One | Two
>prop3 : string | number | boolean
>"hello" : "hello"
u1.prop3 = true;
>u1.prop3 = true : true
>u1.prop3 : string | number | boolean
>u1 : One | Two
>prop3 : string | number | boolean
>true : true
u1.prop4 = 42;
>u1.prop4 = 42 : 42
>u1.prop4 : string | number | boolean
>u1 : One | Two
>prop4 : string | number | boolean
>42 : 42
u1.prop4 = "hello";
>u1.prop4 = "hello" : "hello"
>u1.prop4 : string | number | boolean
>u1 : One | Two
>prop4 : string | number | boolean
>"hello" : "hello"
u1.prop4 = true;
>u1.prop4 = true : true
>u1.prop4 : string | number | boolean
>u1 : One | Two
>prop4 : string | number | boolean
>true : true
@@ -0,0 +1,36 @@
tests/cases/compiler/divergentAccessorsTypes4.ts(29,1): error TS2322: Type '"hello"' is not assignable to type '42'.
==== tests/cases/compiler/divergentAccessorsTypes4.ts (1 errors) ====
class One {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
prop2: number;
}
class Two {
get prop1(): "hello" { return "hello"; }
set prop1(s: "hello" | number) { }
get prop2(): string { return ""; }
set prop2(s: string | 42) { }
}
declare const i: One & Two;
// "hello"
i.prop1;
// number | "hello"
i.prop1 = 42;
i.prop1 = "hello";
// never
i.prop2;
// 42
i.prop2 = 42;
i.prop2 = "hello"; // error
~~~~~~~
!!! error TS2322: Type '"hello"' is not assignable to type '42'.
@@ -0,0 +1,71 @@
//// [divergentAccessorsTypes4.ts]
class One {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
prop2: number;
}
class Two {
get prop1(): "hello" { return "hello"; }
set prop1(s: "hello" | number) { }
get prop2(): string { return ""; }
set prop2(s: string | 42) { }
}
declare const i: One & Two;
// "hello"
i.prop1;
// number | "hello"
i.prop1 = 42;
i.prop1 = "hello";
// never
i.prop2;
// 42
i.prop2 = 42;
i.prop2 = "hello"; // error
//// [divergentAccessorsTypes4.js]
var One = /** @class */ (function () {
function One() {
}
Object.defineProperty(One.prototype, "prop1", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
return One;
}());
var Two = /** @class */ (function () {
function Two() {
}
Object.defineProperty(Two.prototype, "prop1", {
get: function () { return "hello"; },
set: function (s) { },
enumerable: false,
configurable: true
});
Object.defineProperty(Two.prototype, "prop2", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
return Two;
}());
// "hello"
i.prop1;
// number | "hello"
i.prop1 = 42;
i.prop1 = "hello";
// never
i.prop2;
// 42
i.prop2 = 42;
i.prop2 = "hello"; // error
@@ -0,0 +1,73 @@
=== tests/cases/compiler/divergentAccessorsTypes4.ts ===
class One {
>One : Symbol(One, Decl(divergentAccessorsTypes4.ts, 0, 0))
get prop1(): string { return ""; }
>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36))
set prop1(s: string | number) { }
>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes4.ts, 2, 12))
prop2: number;
>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes4.ts, 2, 35))
}
class Two {
>Two : Symbol(Two, Decl(divergentAccessorsTypes4.ts, 5, 1))
get prop1(): "hello" { return "hello"; }
>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42))
set prop1(s: "hello" | number) { }
>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42))
>s : Symbol(s, Decl(divergentAccessorsTypes4.ts, 9, 12))
get prop2(): string { return ""; }
>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36))
set prop2(s: string | 42) { }
>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes4.ts, 12, 12))
}
declare const i: One & Two;
>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13))
>One : Symbol(One, Decl(divergentAccessorsTypes4.ts, 0, 0))
>Two : Symbol(Two, Decl(divergentAccessorsTypes4.ts, 5, 1))
// "hello"
i.prop1;
>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42))
>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13))
>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42))
// number | "hello"
i.prop1 = 42;
>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42))
>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13))
>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42))
i.prop1 = "hello";
>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42))
>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13))
>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42))
// never
i.prop2;
>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36))
>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13))
>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36))
// 42
i.prop2 = 42;
>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36))
>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13))
>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36))
i.prop2 = "hello"; // error
>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36))
>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13))
>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36))
@@ -0,0 +1,82 @@
=== tests/cases/compiler/divergentAccessorsTypes4.ts ===
class One {
>One : One
get prop1(): string { return ""; }
>prop1 : string
>"" : ""
set prop1(s: string | number) { }
>prop1 : string
>s : string | number
prop2: number;
>prop2 : number
}
class Two {
>Two : Two
get prop1(): "hello" { return "hello"; }
>prop1 : "hello"
>"hello" : "hello"
set prop1(s: "hello" | number) { }
>prop1 : "hello"
>s : number | "hello"
get prop2(): string { return ""; }
>prop2 : string
>"" : ""
set prop2(s: string | 42) { }
>prop2 : string
>s : string | 42
}
declare const i: One & Two;
>i : One & Two
// "hello"
i.prop1;
>i.prop1 : "hello"
>i : One & Two
>prop1 : "hello"
// number | "hello"
i.prop1 = 42;
>i.prop1 = 42 : 42
>i.prop1 : number | "hello"
>i : One & Two
>prop1 : number | "hello"
>42 : 42
i.prop1 = "hello";
>i.prop1 = "hello" : "hello"
>i.prop1 : number | "hello"
>i : One & Two
>prop1 : number | "hello"
>"hello" : "hello"
// never
i.prop2;
>i.prop2 : never
>i : One & Two
>prop2 : never
// 42
i.prop2 = 42;
>i.prop2 = 42 : 42
>i.prop2 : 42
>i : One & Two
>prop2 : 42
>42 : 42
i.prop2 = "hello"; // error
>i.prop2 = "hello" : "hello"
>i.prop2 : 42
>i : One & Two
>prop2 : 42
>"hello" : "hello"
@@ -0,0 +1,46 @@
tests/cases/compiler/divergentAccessorsTypes5.ts(31,1): error TS2322: Type '42' is not assignable to type '"hello"'.
tests/cases/compiler/divergentAccessorsTypes5.ts(36,1): error TS2322: Type '"hello"' is not assignable to type '42'.
==== tests/cases/compiler/divergentAccessorsTypes5.ts (2 errors) ====
// Not really different from divergentAccessorsTypes4.ts,
// but goes through the deferred type code
class One {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
prop2: number;
}
class Two {
get prop1(): "hello" { return "hello"; }
set prop1(s: "hello" | number) { }
get prop2(): string { return ""; }
set prop2(s: string | 42) { }
}
class Three {
get prop1(): "hello" { return "hello"; }
set prop1(s: "hello" | boolean) { }
get prop2(): string { return ""; }
set prop2(s: string | number | boolean) { }
}
declare const i: One & Two & Three;
// "hello"
i.prop1 = 42; // error
~~~~~~~
!!! error TS2322: Type '42' is not assignable to type '"hello"'.
i.prop1 = "hello";
// 42
i.prop2 = 42;
i.prop2 = "hello"; // error
~~~~~~~
!!! error TS2322: Type '"hello"' is not assignable to type '42'.
@@ -0,0 +1,93 @@
//// [divergentAccessorsTypes5.ts]
// Not really different from divergentAccessorsTypes4.ts,
// but goes through the deferred type code
class One {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
prop2: number;
}
class Two {
get prop1(): "hello" { return "hello"; }
set prop1(s: "hello" | number) { }
get prop2(): string { return ""; }
set prop2(s: string | 42) { }
}
class Three {
get prop1(): "hello" { return "hello"; }
set prop1(s: "hello" | boolean) { }
get prop2(): string { return ""; }
set prop2(s: string | number | boolean) { }
}
declare const i: One & Two & Three;
// "hello"
i.prop1 = 42; // error
i.prop1 = "hello";
// 42
i.prop2 = 42;
i.prop2 = "hello"; // error
//// [divergentAccessorsTypes5.js]
// Not really different from divergentAccessorsTypes4.ts,
// but goes through the deferred type code
var One = /** @class */ (function () {
function One() {
}
Object.defineProperty(One.prototype, "prop1", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
return One;
}());
var Two = /** @class */ (function () {
function Two() {
}
Object.defineProperty(Two.prototype, "prop1", {
get: function () { return "hello"; },
set: function (s) { },
enumerable: false,
configurable: true
});
Object.defineProperty(Two.prototype, "prop2", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
return Two;
}());
var Three = /** @class */ (function () {
function Three() {
}
Object.defineProperty(Three.prototype, "prop1", {
get: function () { return "hello"; },
set: function (s) { },
enumerable: false,
configurable: true
});
Object.defineProperty(Three.prototype, "prop2", {
get: function () { return ""; },
set: function (s) { },
enumerable: false,
configurable: true
});
return Three;
}());
// "hello"
i.prop1 = 42; // error
i.prop1 = "hello";
// 42
i.prop2 = 42;
i.prop2 = "hello"; // error
@@ -0,0 +1,83 @@
=== tests/cases/compiler/divergentAccessorsTypes5.ts ===
// Not really different from divergentAccessorsTypes4.ts,
// but goes through the deferred type code
class One {
>One : Symbol(One, Decl(divergentAccessorsTypes5.ts, 0, 0))
get prop1(): string { return ""; }
>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36))
set prop1(s: string | number) { }
>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 5, 12))
prop2: number;
>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes5.ts, 5, 35))
}
class Two {
>Two : Symbol(Two, Decl(divergentAccessorsTypes5.ts, 8, 1))
get prop1(): "hello" { return "hello"; }
>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42))
set prop1(s: "hello" | number) { }
>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42))
>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 12, 12))
get prop2(): string { return ""; }
>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36))
set prop2(s: string | 42) { }
>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 15, 12))
}
class Three {
>Three : Symbol(Three, Decl(divergentAccessorsTypes5.ts, 17, 1))
get prop1(): "hello" { return "hello"; }
>prop1 : Symbol(Three.prop1, Decl(divergentAccessorsTypes5.ts, 19, 13), Decl(divergentAccessorsTypes5.ts, 20, 42))
set prop1(s: "hello" | boolean) { }
>prop1 : Symbol(Three.prop1, Decl(divergentAccessorsTypes5.ts, 19, 13), Decl(divergentAccessorsTypes5.ts, 20, 42))
>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 21, 12))
get prop2(): string { return ""; }
>prop2 : Symbol(Three.prop2, Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36))
set prop2(s: string | number | boolean) { }
>prop2 : Symbol(Three.prop2, Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36))
>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 24, 12))
}
declare const i: One & Two & Three;
>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13))
>One : Symbol(One, Decl(divergentAccessorsTypes5.ts, 0, 0))
>Two : Symbol(Two, Decl(divergentAccessorsTypes5.ts, 8, 1))
>Three : Symbol(Three, Decl(divergentAccessorsTypes5.ts, 17, 1))
// "hello"
i.prop1 = 42; // error
>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36), Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42), Decl(divergentAccessorsTypes5.ts, 19, 13) ... and 1 more)
>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13))
>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36), Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42), Decl(divergentAccessorsTypes5.ts, 19, 13) ... and 1 more)
i.prop1 = "hello";
>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36), Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42), Decl(divergentAccessorsTypes5.ts, 19, 13) ... and 1 more)
>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13))
>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36), Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42), Decl(divergentAccessorsTypes5.ts, 19, 13) ... and 1 more)
// 42
i.prop2 = 42;
>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes5.ts, 5, 35), Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36), Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36))
>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13))
>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes5.ts, 5, 35), Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36), Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36))
i.prop2 = "hello"; // error
>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes5.ts, 5, 35), Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36), Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36))
>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13))
>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes5.ts, 5, 35), Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36), Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36))
@@ -0,0 +1,93 @@
=== tests/cases/compiler/divergentAccessorsTypes5.ts ===
// Not really different from divergentAccessorsTypes4.ts,
// but goes through the deferred type code
class One {
>One : One
get prop1(): string { return ""; }
>prop1 : string
>"" : ""
set prop1(s: string | number) { }
>prop1 : string
>s : string | number
prop2: number;
>prop2 : number
}
class Two {
>Two : Two
get prop1(): "hello" { return "hello"; }
>prop1 : "hello"
>"hello" : "hello"
set prop1(s: "hello" | number) { }
>prop1 : "hello"
>s : number | "hello"
get prop2(): string { return ""; }
>prop2 : string
>"" : ""
set prop2(s: string | 42) { }
>prop2 : string
>s : string | 42
}
class Three {
>Three : Three
get prop1(): "hello" { return "hello"; }
>prop1 : "hello"
>"hello" : "hello"
set prop1(s: "hello" | boolean) { }
>prop1 : "hello"
>s : boolean | "hello"
get prop2(): string { return ""; }
>prop2 : string
>"" : ""
set prop2(s: string | number | boolean) { }
>prop2 : string
>s : string | number | boolean
}
declare const i: One & Two & Three;
>i : One & Two & Three
// "hello"
i.prop1 = 42; // error
>i.prop1 = 42 : 42
>i.prop1 : "hello"
>i : One & Two & Three
>prop1 : "hello"
>42 : 42
i.prop1 = "hello";
>i.prop1 = "hello" : "hello"
>i.prop1 : "hello"
>i : One & Two & Three
>prop1 : "hello"
>"hello" : "hello"
// 42
i.prop2 = 42;
>i.prop2 = 42 : 42
>i.prop2 : 42
>i : One & Two & Three
>prop2 : 42
>42 : 42
i.prop2 = "hello"; // error
>i.prop2 = "hello" : "hello"
>i.prop2 : 42
>i : One & Two & Three
>prop2 : 42
>"hello" : "hello"
@@ -0,0 +1,44 @@
// @target: es5
class One {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
get prop2(): string { return ""; }
set prop2(s: string | number) { }
prop3: number;
get prop4(): string { return ""; }
set prop4(s: string | number) { }
}
class Two {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
get prop2(): string { return ""; }
set prop2(s: string) { }
get prop3(): string { return ""; }
set prop3(s: string | boolean) { }
get prop4(): string { return ""; }
set prop4(s: string | boolean) { }
}
declare const u1: One|Two;
u1.prop1 = 42;
u1.prop1 = "hello";
u1.prop2 = 42;
u1.prop2 = "hello";
u1.prop3 = 42;
u1.prop3 = "hello";
u1.prop3 = true;
u1.prop4 = 42;
u1.prop4 = "hello";
u1.prop4 = true;
@@ -0,0 +1,31 @@
// @target: es5
class One {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
prop2: number;
}
class Two {
get prop1(): "hello" { return "hello"; }
set prop1(s: "hello" | number) { }
get prop2(): string { return ""; }
set prop2(s: string | 42) { }
}
declare const i: One & Two;
// "hello"
i.prop1;
// number | "hello"
i.prop1 = 42;
i.prop1 = "hello";
// never
i.prop2;
// 42
i.prop2 = 42;
i.prop2 = "hello"; // error
@@ -0,0 +1,38 @@
// @target: es5
// Not really different from divergentAccessorsTypes4.ts,
// but goes through the deferred type code
class One {
get prop1(): string { return ""; }
set prop1(s: string | number) { }
prop2: number;
}
class Two {
get prop1(): "hello" { return "hello"; }
set prop1(s: "hello" | number) { }
get prop2(): string { return ""; }
set prop2(s: string | 42) { }
}
class Three {
get prop1(): "hello" { return "hello"; }
set prop1(s: "hello" | boolean) { }
get prop2(): string { return ""; }
set prop2(s: string | number | boolean) { }
}
declare const i: One & Two & Three;
// "hello"
i.prop1 = 42; // error
i.prop1 = "hello";
// 42
i.prop2 = 42;
i.prop2 = "hello"; // error