Fixed element access expression writes for divergent write types (#55585)

This commit is contained in:
Mateusz Burzyński 2023-09-14 01:14:07 +02:00 committed by GitHub
parent c0b39c6967
commit e6321d77c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1182 additions and 12 deletions

View File

@ -686,6 +686,7 @@ import {
isRequireCall,
isRestParameter,
isRestTypeNode,
isRightSideOfAccessExpression,
isRightSideOfQualifiedNameOrPropertyAccess,
isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName,
isSameEntityName,
@ -17737,7 +17738,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return autoType;
}
}
const propType = getTypeOfSymbol(prop);
const propType = accessFlags & AccessFlags.Writing ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop);
return accessExpression && getAssignmentTargetKind(accessExpression) !== AssignmentKind.Definite ? getFlowTypeOfReference(accessExpression, propType) :
accessNode && isIndexedAccessTypeNode(accessNode) && containsMissingType(propType) ? getUnionType([propType, undefinedType]) :
propType;
@ -28229,7 +28230,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// to it at the given location. Since we have no control flow information for the
// hypothetical reference (control flow information is created and attached by the
// binder), we simply return the declared type of the symbol.
return getNonMissingTypeOfSymbol(symbol);
return isRightSideOfAccessExpression(location) && isWriteAccess(location.parent) ? getWriteTypeOfSymbol(symbol) : getNonMissingTypeOfSymbol(symbol);
}
function getControlFlowContainer(node: Node): Node {

View File

@ -7259,8 +7259,8 @@ export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
/** @internal */
export function isRightSideOfAccessExpression(node: Node) {
return isPropertyAccessExpression(node.parent) && node.parent.name === node
|| isElementAccessExpression(node.parent) && node.parent.argumentExpression === node;
return !!node.parent && (isPropertyAccessExpression(node.parent) && node.parent.name === node
|| isElementAccessExpression(node.parent) && node.parent.argumentExpression === node);
}
/** @internal */

View File

@ -9,12 +9,12 @@ class Test<S> {
get value(): string {
return null!;
}
// -- Replacing the getter such that the getter/setter types match, removes the error:
// get value(): string | ((item: S) => string) {
// return null!;
// }
// -- Or, replacing the setter such that a concrete type is used, removes the error:
// set value(value: string | ((item: { property: string }) => string)) {}
}
@ -24,6 +24,7 @@ const a = new Test<{
}>();
a.value = (item) => item.property
a['value'] = (item) => item.property
//// [divergentAccessorsTypes7.js]
@ -42,3 +43,4 @@ var Test = /** @class */ (function () {
}());
var a = new Test();
a.value = function (item) { return item.property; };
a['value'] = function (item) { return item.property; };

View File

@ -18,12 +18,12 @@ class Test<S> {
return null!;
}
// -- Replacing the getter such that the getter/setter types match, removes the error:
// get value(): string | ((item: S) => string) {
// return null!;
// }
// -- Or, replacing the setter such that a concrete type is used, removes the error:
// set value(value: string | ((item: { property: string }) => string)) {}
}
@ -46,3 +46,11 @@ a.value = (item) => item.property
>item : Symbol(item, Decl(divergentAccessorsTypes7.ts, 22, 11))
>property : Symbol(property, Decl(divergentAccessorsTypes7.ts, 18, 20))
a['value'] = (item) => item.property
>a : Symbol(a, Decl(divergentAccessorsTypes7.ts, 18, 5))
>'value' : Symbol(Test.value, Decl(divergentAccessorsTypes7.ts, 1, 20), Decl(divergentAccessorsTypes7.ts, 3, 55))
>item : Symbol(item, Decl(divergentAccessorsTypes7.ts, 23, 14))
>item.property : Symbol(property, Decl(divergentAccessorsTypes7.ts, 18, 20))
>item : Symbol(item, Decl(divergentAccessorsTypes7.ts, 23, 14))
>property : Symbol(property, Decl(divergentAccessorsTypes7.ts, 18, 20))

View File

@ -17,12 +17,12 @@ class Test<S> {
return null!;
>null! : null
}
// -- Replacing the getter such that the getter/setter types match, removes the error:
// get value(): string | ((item: S) => string) {
// return null!;
// }
// -- Or, replacing the setter such that a concrete type is used, removes the error:
// set value(value: string | ((item: { property: string }) => string)) {}
}
@ -48,3 +48,14 @@ a.value = (item) => item.property
>item : { property: string; }
>property : string
a['value'] = (item) => item.property
>a['value'] = (item) => item.property : (item: { property: string; }) => string
>a['value'] : string | ((item: { property: string; }) => string)
>a : Test<{ property: string; }>
>'value' : "value"
>(item) => item.property : (item: { property: string; }) => string
>item : { property: string; }
>item.property : string
>item : { property: string; }
>property : string

View File

@ -0,0 +1,174 @@
divergentAccessorsTypes8.ts(20,1): error TS2322: Type 'CSSStyleDeclaration' is not assignable to type 'string'.
divergentAccessorsTypes8.ts(86,1): error TS2322: Type 'number' is not assignable to type 'string'.
divergentAccessorsTypes8.ts(124,1): error TS2322: Type '42' is not assignable to type '"hello"'.
divergentAccessorsTypes8.ts(128,1): error TS2322: Type '"hello"' is not assignable to type '42'.
divergentAccessorsTypes8.ts(146,1): error TS2322: Type 'number' is not assignable to type 'boolean'.
divergentAccessorsTypes8.ts(148,1): error TS2322: Type 'string' is not assignable to type 'boolean'.
divergentAccessorsTypes8.ts(149,1): error TS2322: Type 'null' is not assignable to type 'boolean'.
==== divergentAccessorsTypes8.ts (7 errors) ====
export {}
interface Serializer {
set value(v: string | number | boolean);
get value(): string;
}
declare let box: Serializer;
const v = box['value']
box['value'] = true;
box['value'] = 42;
box['value'] = "hello";
interface Element {
get style(): CSSStyleDeclaration;
set style(cssText: string);
}
declare const element: Element;
element['style'] = "color: red";
element['style'] = element.style;
~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'CSSStyleDeclaration' is not assignable to type 'string'.
class One {
get prop1(): string {
return "";
}
set prop1(s: string | number) {}
get prop2(): string {
return "";
}
set prop2(s: string | number) {}
prop3: number = 42;
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;
declare const i: One & Two;
const iv1 = i['prop1'];
i['prop1'] = 42;
i['prop1'] = "hello";
const iv2 = i['prop2'];
i['prop2'] = 42;
~~~~~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
i['prop2'] = "hello";
class Three {
get prop1(): string {
return "";
}
set prop1(s: string | number) {}
prop2: number = 42;
}
class Four {
get prop1(): "hello" {
return "hello";
}
set prop1(s: "hello" | number) {}
get prop2(): string {
return "";
}
set prop2(s: string | 42) {}
}
class Five {
get prop1(): "hello" {
return "hello";
}
set prop1(s: "hello" | boolean) {}
get prop2(): string {
return "";
}
set prop2(s: string | number | boolean) {}
}
declare const i2: Three & Four & Five;
i2['prop1'] = 42;
~~~~~~~~~~~
!!! error TS2322: Type '42' is not assignable to type '"hello"'.
i2['prop1'] = "hello";
i2['prop2'] = 42;
i2['prop2'] = "hello";
~~~~~~~~~~~
!!! error TS2322: Type '"hello"' is not assignable to type '42'.
class Six {
get prop1(): boolean | number {
return 42;
}
set prop1(s: boolean | string) {}
get prop2(): bigint | number {
return 10;
}
set prop2(s: boolean | null) {}
}
declare const s1: Six
declare const k1: 'prop1' | 'prop2'
const sv1 = s1[k1]
s1[k1] = 42
~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'boolean'.
s1[k1] = true
s1[k1] = ''
~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
s1[k1] = null
~~~~~~
!!! error TS2322: Type 'null' is not assignable to type 'boolean'.

View File

@ -0,0 +1,345 @@
//// [tests/cases/compiler/divergentAccessorsTypes8.ts] ////
=== divergentAccessorsTypes8.ts ===
export {}
interface Serializer {
>Serializer : Symbol(Serializer, Decl(divergentAccessorsTypes8.ts, 0, 9))
set value(v: string | number | boolean);
>value : Symbol(Serializer.value, Decl(divergentAccessorsTypes8.ts, 2, 22), Decl(divergentAccessorsTypes8.ts, 3, 42))
>v : Symbol(v, Decl(divergentAccessorsTypes8.ts, 3, 12))
get value(): string;
>value : Symbol(Serializer.value, Decl(divergentAccessorsTypes8.ts, 2, 22), Decl(divergentAccessorsTypes8.ts, 3, 42))
}
declare let box: Serializer;
>box : Symbol(box, Decl(divergentAccessorsTypes8.ts, 6, 11))
>Serializer : Symbol(Serializer, Decl(divergentAccessorsTypes8.ts, 0, 9))
const v = box['value']
>v : Symbol(v, Decl(divergentAccessorsTypes8.ts, 7, 5))
>box : Symbol(box, Decl(divergentAccessorsTypes8.ts, 6, 11))
>'value' : Symbol(Serializer.value, Decl(divergentAccessorsTypes8.ts, 2, 22), Decl(divergentAccessorsTypes8.ts, 3, 42))
box['value'] = true;
>box : Symbol(box, Decl(divergentAccessorsTypes8.ts, 6, 11))
>'value' : Symbol(Serializer.value, Decl(divergentAccessorsTypes8.ts, 2, 22), Decl(divergentAccessorsTypes8.ts, 3, 42))
box['value'] = 42;
>box : Symbol(box, Decl(divergentAccessorsTypes8.ts, 6, 11))
>'value' : Symbol(Serializer.value, Decl(divergentAccessorsTypes8.ts, 2, 22), Decl(divergentAccessorsTypes8.ts, 3, 42))
box['value'] = "hello";
>box : Symbol(box, Decl(divergentAccessorsTypes8.ts, 6, 11))
>'value' : Symbol(Serializer.value, Decl(divergentAccessorsTypes8.ts, 2, 22), Decl(divergentAccessorsTypes8.ts, 3, 42))
interface Element {
>Element : Symbol(Element, Decl(divergentAccessorsTypes8.ts, 10, 23))
get style(): CSSStyleDeclaration;
>style : Symbol(Element.style, Decl(divergentAccessorsTypes8.ts, 12, 19), Decl(divergentAccessorsTypes8.ts, 13, 37))
>CSSStyleDeclaration : Symbol(CSSStyleDeclaration, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
set style(cssText: string);
>style : Symbol(Element.style, Decl(divergentAccessorsTypes8.ts, 12, 19), Decl(divergentAccessorsTypes8.ts, 13, 37))
>cssText : Symbol(cssText, Decl(divergentAccessorsTypes8.ts, 14, 14))
}
declare const element: Element;
>element : Symbol(element, Decl(divergentAccessorsTypes8.ts, 17, 13))
>Element : Symbol(Element, Decl(divergentAccessorsTypes8.ts, 10, 23))
element['style'] = "color: red";
>element : Symbol(element, Decl(divergentAccessorsTypes8.ts, 17, 13))
>'style' : Symbol(Element.style, Decl(divergentAccessorsTypes8.ts, 12, 19), Decl(divergentAccessorsTypes8.ts, 13, 37))
element['style'] = element.style;
>element : Symbol(element, Decl(divergentAccessorsTypes8.ts, 17, 13))
>'style' : Symbol(Element.style, Decl(divergentAccessorsTypes8.ts, 12, 19), Decl(divergentAccessorsTypes8.ts, 13, 37))
>element.style : Symbol(Element.style, Decl(divergentAccessorsTypes8.ts, 12, 19), Decl(divergentAccessorsTypes8.ts, 13, 37))
>element : Symbol(element, Decl(divergentAccessorsTypes8.ts, 17, 13))
>style : Symbol(Element.style, Decl(divergentAccessorsTypes8.ts, 12, 19), Decl(divergentAccessorsTypes8.ts, 13, 37))
class One {
>One : Symbol(One, Decl(divergentAccessorsTypes8.ts, 19, 33))
get prop1(): string {
>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes8.ts, 21, 11), Decl(divergentAccessorsTypes8.ts, 24, 3))
return "";
}
set prop1(s: string | number) {}
>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes8.ts, 21, 11), Decl(divergentAccessorsTypes8.ts, 24, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 25, 12))
get prop2(): string {
>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes8.ts, 25, 34), Decl(divergentAccessorsTypes8.ts, 29, 3))
return "";
}
set prop2(s: string | number) {}
>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes8.ts, 25, 34), Decl(divergentAccessorsTypes8.ts, 29, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 30, 12))
prop3: number = 42;
>prop3 : Symbol(One.prop3, Decl(divergentAccessorsTypes8.ts, 30, 34))
get prop4(): string {
>prop4 : Symbol(One.prop4, Decl(divergentAccessorsTypes8.ts, 32, 21), Decl(divergentAccessorsTypes8.ts, 36, 3))
return "";
}
set prop4(s: string | number) {}
>prop4 : Symbol(One.prop4, Decl(divergentAccessorsTypes8.ts, 32, 21), Decl(divergentAccessorsTypes8.ts, 36, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 37, 12))
}
class Two {
>Two : Symbol(Two, Decl(divergentAccessorsTypes8.ts, 38, 1))
get prop1(): string {
>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes8.ts, 40, 11), Decl(divergentAccessorsTypes8.ts, 43, 3))
return "";
}
set prop1(s: string | number) {}
>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes8.ts, 40, 11), Decl(divergentAccessorsTypes8.ts, 43, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 44, 12))
get prop2(): string {
>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes8.ts, 44, 34), Decl(divergentAccessorsTypes8.ts, 48, 3))
return "";
}
set prop2(s: string) {}
>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes8.ts, 44, 34), Decl(divergentAccessorsTypes8.ts, 48, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 49, 12))
get prop3(): string {
>prop3 : Symbol(Two.prop3, Decl(divergentAccessorsTypes8.ts, 49, 25), Decl(divergentAccessorsTypes8.ts, 53, 3))
return "";
}
set prop3(s: string | boolean) {}
>prop3 : Symbol(Two.prop3, Decl(divergentAccessorsTypes8.ts, 49, 25), Decl(divergentAccessorsTypes8.ts, 53, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 54, 12))
get prop4(): string {
>prop4 : Symbol(Two.prop4, Decl(divergentAccessorsTypes8.ts, 54, 35), Decl(divergentAccessorsTypes8.ts, 58, 3))
return "";
}
set prop4(s: string | boolean) {}
>prop4 : Symbol(Two.prop4, Decl(divergentAccessorsTypes8.ts, 54, 35), Decl(divergentAccessorsTypes8.ts, 58, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 59, 12))
}
declare const u1: One | Two;
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>One : Symbol(One, Decl(divergentAccessorsTypes8.ts, 19, 33))
>Two : Symbol(Two, Decl(divergentAccessorsTypes8.ts, 38, 1))
u1['prop1'] = 42;
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop1' : Symbol(prop1, Decl(divergentAccessorsTypes8.ts, 21, 11), Decl(divergentAccessorsTypes8.ts, 24, 3), Decl(divergentAccessorsTypes8.ts, 40, 11), Decl(divergentAccessorsTypes8.ts, 43, 3))
u1['prop1'] = "hello";
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop1' : Symbol(prop1, Decl(divergentAccessorsTypes8.ts, 21, 11), Decl(divergentAccessorsTypes8.ts, 24, 3), Decl(divergentAccessorsTypes8.ts, 40, 11), Decl(divergentAccessorsTypes8.ts, 43, 3))
u1['prop2'] = 42;
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop2' : Symbol(prop2, Decl(divergentAccessorsTypes8.ts, 25, 34), Decl(divergentAccessorsTypes8.ts, 29, 3), Decl(divergentAccessorsTypes8.ts, 44, 34), Decl(divergentAccessorsTypes8.ts, 48, 3))
u1['prop2'] = "hello";
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop2' : Symbol(prop2, Decl(divergentAccessorsTypes8.ts, 25, 34), Decl(divergentAccessorsTypes8.ts, 29, 3), Decl(divergentAccessorsTypes8.ts, 44, 34), Decl(divergentAccessorsTypes8.ts, 48, 3))
u1['prop3'] = 42;
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop3' : Symbol(prop3, Decl(divergentAccessorsTypes8.ts, 30, 34), Decl(divergentAccessorsTypes8.ts, 49, 25), Decl(divergentAccessorsTypes8.ts, 53, 3))
u1['prop3'] = "hello";
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop3' : Symbol(prop3, Decl(divergentAccessorsTypes8.ts, 30, 34), Decl(divergentAccessorsTypes8.ts, 49, 25), Decl(divergentAccessorsTypes8.ts, 53, 3))
u1['prop3'] = true;
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop3' : Symbol(prop3, Decl(divergentAccessorsTypes8.ts, 30, 34), Decl(divergentAccessorsTypes8.ts, 49, 25), Decl(divergentAccessorsTypes8.ts, 53, 3))
u1['prop4'] = 42;
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop4' : Symbol(prop4, Decl(divergentAccessorsTypes8.ts, 32, 21), Decl(divergentAccessorsTypes8.ts, 36, 3), Decl(divergentAccessorsTypes8.ts, 54, 35), Decl(divergentAccessorsTypes8.ts, 58, 3))
u1['prop4'] = "hello";
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop4' : Symbol(prop4, Decl(divergentAccessorsTypes8.ts, 32, 21), Decl(divergentAccessorsTypes8.ts, 36, 3), Decl(divergentAccessorsTypes8.ts, 54, 35), Decl(divergentAccessorsTypes8.ts, 58, 3))
u1['prop4'] = true;
>u1 : Symbol(u1, Decl(divergentAccessorsTypes8.ts, 62, 13))
>'prop4' : Symbol(prop4, Decl(divergentAccessorsTypes8.ts, 32, 21), Decl(divergentAccessorsTypes8.ts, 36, 3), Decl(divergentAccessorsTypes8.ts, 54, 35), Decl(divergentAccessorsTypes8.ts, 58, 3))
declare const i: One & Two;
>i : Symbol(i, Decl(divergentAccessorsTypes8.ts, 78, 13))
>One : Symbol(One, Decl(divergentAccessorsTypes8.ts, 19, 33))
>Two : Symbol(Two, Decl(divergentAccessorsTypes8.ts, 38, 1))
const iv1 = i['prop1'];
>iv1 : Symbol(iv1, Decl(divergentAccessorsTypes8.ts, 80, 5))
>i : Symbol(i, Decl(divergentAccessorsTypes8.ts, 78, 13))
>'prop1' : Symbol(prop1, Decl(divergentAccessorsTypes8.ts, 21, 11), Decl(divergentAccessorsTypes8.ts, 24, 3), Decl(divergentAccessorsTypes8.ts, 40, 11), Decl(divergentAccessorsTypes8.ts, 43, 3))
i['prop1'] = 42;
>i : Symbol(i, Decl(divergentAccessorsTypes8.ts, 78, 13))
>'prop1' : Symbol(prop1, Decl(divergentAccessorsTypes8.ts, 21, 11), Decl(divergentAccessorsTypes8.ts, 24, 3), Decl(divergentAccessorsTypes8.ts, 40, 11), Decl(divergentAccessorsTypes8.ts, 43, 3))
i['prop1'] = "hello";
>i : Symbol(i, Decl(divergentAccessorsTypes8.ts, 78, 13))
>'prop1' : Symbol(prop1, Decl(divergentAccessorsTypes8.ts, 21, 11), Decl(divergentAccessorsTypes8.ts, 24, 3), Decl(divergentAccessorsTypes8.ts, 40, 11), Decl(divergentAccessorsTypes8.ts, 43, 3))
const iv2 = i['prop2'];
>iv2 : Symbol(iv2, Decl(divergentAccessorsTypes8.ts, 84, 5))
>i : Symbol(i, Decl(divergentAccessorsTypes8.ts, 78, 13))
>'prop2' : Symbol(prop2, Decl(divergentAccessorsTypes8.ts, 25, 34), Decl(divergentAccessorsTypes8.ts, 29, 3), Decl(divergentAccessorsTypes8.ts, 44, 34), Decl(divergentAccessorsTypes8.ts, 48, 3))
i['prop2'] = 42;
>i : Symbol(i, Decl(divergentAccessorsTypes8.ts, 78, 13))
>'prop2' : Symbol(prop2, Decl(divergentAccessorsTypes8.ts, 25, 34), Decl(divergentAccessorsTypes8.ts, 29, 3), Decl(divergentAccessorsTypes8.ts, 44, 34), Decl(divergentAccessorsTypes8.ts, 48, 3))
i['prop2'] = "hello";
>i : Symbol(i, Decl(divergentAccessorsTypes8.ts, 78, 13))
>'prop2' : Symbol(prop2, Decl(divergentAccessorsTypes8.ts, 25, 34), Decl(divergentAccessorsTypes8.ts, 29, 3), Decl(divergentAccessorsTypes8.ts, 44, 34), Decl(divergentAccessorsTypes8.ts, 48, 3))
class Three {
>Three : Symbol(Three, Decl(divergentAccessorsTypes8.ts, 86, 21))
get prop1(): string {
>prop1 : Symbol(Three.prop1, Decl(divergentAccessorsTypes8.ts, 88, 13), Decl(divergentAccessorsTypes8.ts, 91, 3))
return "";
}
set prop1(s: string | number) {}
>prop1 : Symbol(Three.prop1, Decl(divergentAccessorsTypes8.ts, 88, 13), Decl(divergentAccessorsTypes8.ts, 91, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 92, 12))
prop2: number = 42;
>prop2 : Symbol(Three.prop2, Decl(divergentAccessorsTypes8.ts, 92, 34))
}
class Four {
>Four : Symbol(Four, Decl(divergentAccessorsTypes8.ts, 95, 1))
get prop1(): "hello" {
>prop1 : Symbol(Four.prop1, Decl(divergentAccessorsTypes8.ts, 97, 12), Decl(divergentAccessorsTypes8.ts, 100, 3))
return "hello";
}
set prop1(s: "hello" | number) {}
>prop1 : Symbol(Four.prop1, Decl(divergentAccessorsTypes8.ts, 97, 12), Decl(divergentAccessorsTypes8.ts, 100, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 101, 12))
get prop2(): string {
>prop2 : Symbol(Four.prop2, Decl(divergentAccessorsTypes8.ts, 101, 35), Decl(divergentAccessorsTypes8.ts, 105, 3))
return "";
}
set prop2(s: string | 42) {}
>prop2 : Symbol(Four.prop2, Decl(divergentAccessorsTypes8.ts, 101, 35), Decl(divergentAccessorsTypes8.ts, 105, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 106, 12))
}
class Five {
>Five : Symbol(Five, Decl(divergentAccessorsTypes8.ts, 107, 1))
get prop1(): "hello" {
>prop1 : Symbol(Five.prop1, Decl(divergentAccessorsTypes8.ts, 109, 12), Decl(divergentAccessorsTypes8.ts, 112, 3))
return "hello";
}
set prop1(s: "hello" | boolean) {}
>prop1 : Symbol(Five.prop1, Decl(divergentAccessorsTypes8.ts, 109, 12), Decl(divergentAccessorsTypes8.ts, 112, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 113, 12))
get prop2(): string {
>prop2 : Symbol(Five.prop2, Decl(divergentAccessorsTypes8.ts, 113, 36), Decl(divergentAccessorsTypes8.ts, 117, 3))
return "";
}
set prop2(s: string | number | boolean) {}
>prop2 : Symbol(Five.prop2, Decl(divergentAccessorsTypes8.ts, 113, 36), Decl(divergentAccessorsTypes8.ts, 117, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 118, 12))
}
declare const i2: Three & Four & Five;
>i2 : Symbol(i2, Decl(divergentAccessorsTypes8.ts, 121, 13))
>Three : Symbol(Three, Decl(divergentAccessorsTypes8.ts, 86, 21))
>Four : Symbol(Four, Decl(divergentAccessorsTypes8.ts, 95, 1))
>Five : Symbol(Five, Decl(divergentAccessorsTypes8.ts, 107, 1))
i2['prop1'] = 42;
>i2 : Symbol(i2, Decl(divergentAccessorsTypes8.ts, 121, 13))
>'prop1' : Symbol(prop1, Decl(divergentAccessorsTypes8.ts, 88, 13), Decl(divergentAccessorsTypes8.ts, 91, 3), Decl(divergentAccessorsTypes8.ts, 97, 12), Decl(divergentAccessorsTypes8.ts, 100, 3), Decl(divergentAccessorsTypes8.ts, 109, 12) ... and 1 more)
i2['prop1'] = "hello";
>i2 : Symbol(i2, Decl(divergentAccessorsTypes8.ts, 121, 13))
>'prop1' : Symbol(prop1, Decl(divergentAccessorsTypes8.ts, 88, 13), Decl(divergentAccessorsTypes8.ts, 91, 3), Decl(divergentAccessorsTypes8.ts, 97, 12), Decl(divergentAccessorsTypes8.ts, 100, 3), Decl(divergentAccessorsTypes8.ts, 109, 12) ... and 1 more)
i2['prop2'] = 42;
>i2 : Symbol(i2, Decl(divergentAccessorsTypes8.ts, 121, 13))
>'prop2' : Symbol(prop2, Decl(divergentAccessorsTypes8.ts, 92, 34), Decl(divergentAccessorsTypes8.ts, 101, 35), Decl(divergentAccessorsTypes8.ts, 105, 3), Decl(divergentAccessorsTypes8.ts, 113, 36), Decl(divergentAccessorsTypes8.ts, 117, 3))
i2['prop2'] = "hello";
>i2 : Symbol(i2, Decl(divergentAccessorsTypes8.ts, 121, 13))
>'prop2' : Symbol(prop2, Decl(divergentAccessorsTypes8.ts, 92, 34), Decl(divergentAccessorsTypes8.ts, 101, 35), Decl(divergentAccessorsTypes8.ts, 105, 3), Decl(divergentAccessorsTypes8.ts, 113, 36), Decl(divergentAccessorsTypes8.ts, 117, 3))
class Six {
>Six : Symbol(Six, Decl(divergentAccessorsTypes8.ts, 127, 22))
get prop1(): boolean | number {
>prop1 : Symbol(Six.prop1, Decl(divergentAccessorsTypes8.ts, 129, 11), Decl(divergentAccessorsTypes8.ts, 132, 3))
return 42;
}
set prop1(s: boolean | string) {}
>prop1 : Symbol(Six.prop1, Decl(divergentAccessorsTypes8.ts, 129, 11), Decl(divergentAccessorsTypes8.ts, 132, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 133, 12))
get prop2(): bigint | number {
>prop2 : Symbol(Six.prop2, Decl(divergentAccessorsTypes8.ts, 133, 35), Decl(divergentAccessorsTypes8.ts, 137, 3))
return 10;
}
set prop2(s: boolean | null) {}
>prop2 : Symbol(Six.prop2, Decl(divergentAccessorsTypes8.ts, 133, 35), Decl(divergentAccessorsTypes8.ts, 137, 3))
>s : Symbol(s, Decl(divergentAccessorsTypes8.ts, 138, 12))
}
declare const s1: Six
>s1 : Symbol(s1, Decl(divergentAccessorsTypes8.ts, 141, 13))
>Six : Symbol(Six, Decl(divergentAccessorsTypes8.ts, 127, 22))
declare const k1: 'prop1' | 'prop2'
>k1 : Symbol(k1, Decl(divergentAccessorsTypes8.ts, 142, 13))
const sv1 = s1[k1]
>sv1 : Symbol(sv1, Decl(divergentAccessorsTypes8.ts, 144, 5))
>s1 : Symbol(s1, Decl(divergentAccessorsTypes8.ts, 141, 13))
>k1 : Symbol(k1, Decl(divergentAccessorsTypes8.ts, 142, 13))
s1[k1] = 42
>s1 : Symbol(s1, Decl(divergentAccessorsTypes8.ts, 141, 13))
>k1 : Symbol(k1, Decl(divergentAccessorsTypes8.ts, 142, 13))
s1[k1] = true
>s1 : Symbol(s1, Decl(divergentAccessorsTypes8.ts, 141, 13))
>k1 : Symbol(k1, Decl(divergentAccessorsTypes8.ts, 142, 13))
s1[k1] = ''
>s1 : Symbol(s1, Decl(divergentAccessorsTypes8.ts, 141, 13))
>k1 : Symbol(k1, Decl(divergentAccessorsTypes8.ts, 142, 13))
s1[k1] = null
>s1 : Symbol(s1, Decl(divergentAccessorsTypes8.ts, 141, 13))
>k1 : Symbol(k1, Decl(divergentAccessorsTypes8.ts, 142, 13))

View File

@ -0,0 +1,429 @@
//// [tests/cases/compiler/divergentAccessorsTypes8.ts] ////
=== divergentAccessorsTypes8.ts ===
export {}
interface Serializer {
set value(v: string | number | boolean);
>value : string
>v : string | number | boolean
get value(): string;
>value : string
}
declare let box: Serializer;
>box : Serializer
const v = box['value']
>v : string
>box['value'] : string
>box : Serializer
>'value' : "value"
box['value'] = true;
>box['value'] = true : true
>box['value'] : string | number | boolean
>box : Serializer
>'value' : "value"
>true : true
box['value'] = 42;
>box['value'] = 42 : 42
>box['value'] : string | number | boolean
>box : Serializer
>'value' : "value"
>42 : 42
box['value'] = "hello";
>box['value'] = "hello" : "hello"
>box['value'] : string | number | boolean
>box : Serializer
>'value' : "value"
>"hello" : "hello"
interface Element {
get style(): CSSStyleDeclaration;
>style : CSSStyleDeclaration
set style(cssText: string);
>style : CSSStyleDeclaration
>cssText : string
}
declare const element: Element;
>element : Element
element['style'] = "color: red";
>element['style'] = "color: red" : "color: red"
>element['style'] : string
>element : Element
>'style' : "style"
>"color: red" : "color: red"
element['style'] = element.style;
>element['style'] = element.style : CSSStyleDeclaration
>element['style'] : string
>element : Element
>'style' : "style"
>element.style : CSSStyleDeclaration
>element : Element
>style : CSSStyleDeclaration
class One {
>One : One
get prop1(): string {
>prop1 : string
return "";
>"" : ""
}
set prop1(s: string | number) {}
>prop1 : string
>s : string | number
get prop2(): string {
>prop2 : string
return "";
>"" : ""
}
set prop2(s: string | number) {}
>prop2 : string
>s : string | number
prop3: number = 42;
>prop3 : number
>42 : 42
get prop4(): string {
>prop4 : string
return "";
>"" : ""
}
set prop4(s: string | number) {}
>prop4 : string
>s : string | number
}
class Two {
>Two : Two
get prop1(): string {
>prop1 : string
return "";
>"" : ""
}
set prop1(s: string | number) {}
>prop1 : string
>s : string | number
get prop2(): string {
>prop2 : string
return "";
>"" : ""
}
set prop2(s: string) {}
>prop2 : string
>s : string
get prop3(): string {
>prop3 : string
return "";
>"" : ""
}
set prop3(s: string | boolean) {}
>prop3 : string
>s : string | boolean
get prop4(): string {
>prop4 : string
return "";
>"" : ""
}
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' : "prop1"
>42 : 42
u1['prop1'] = "hello";
>u1['prop1'] = "hello" : "hello"
>u1['prop1'] : string | number
>u1 : One | Two
>'prop1' : "prop1"
>"hello" : "hello"
u1['prop2'] = 42;
>u1['prop2'] = 42 : 42
>u1['prop2'] : string | number
>u1 : One | Two
>'prop2' : "prop2"
>42 : 42
u1['prop2'] = "hello";
>u1['prop2'] = "hello" : "hello"
>u1['prop2'] : string | number
>u1 : One | Two
>'prop2' : "prop2"
>"hello" : "hello"
u1['prop3'] = 42;
>u1['prop3'] = 42 : 42
>u1['prop3'] : string | number | boolean
>u1 : One | Two
>'prop3' : "prop3"
>42 : 42
u1['prop3'] = "hello";
>u1['prop3'] = "hello" : "hello"
>u1['prop3'] : string | number | boolean
>u1 : One | Two
>'prop3' : "prop3"
>"hello" : "hello"
u1['prop3'] = true;
>u1['prop3'] = true : true
>u1['prop3'] : string | number | boolean
>u1 : One | Two
>'prop3' : "prop3"
>true : true
u1['prop4'] = 42;
>u1['prop4'] = 42 : 42
>u1['prop4'] : string | number | boolean
>u1 : One | Two
>'prop4' : "prop4"
>42 : 42
u1['prop4'] = "hello";
>u1['prop4'] = "hello" : "hello"
>u1['prop4'] : string | number | boolean
>u1 : One | Two
>'prop4' : "prop4"
>"hello" : "hello"
u1['prop4'] = true;
>u1['prop4'] = true : true
>u1['prop4'] : string | number | boolean
>u1 : One | Two
>'prop4' : "prop4"
>true : true
declare const i: One & Two;
>i : One & Two
const iv1 = i['prop1'];
>iv1 : string
>i['prop1'] : string
>i : One & Two
>'prop1' : "prop1"
i['prop1'] = 42;
>i['prop1'] = 42 : 42
>i['prop1'] : string | number
>i : One & Two
>'prop1' : "prop1"
>42 : 42
i['prop1'] = "hello";
>i['prop1'] = "hello" : "hello"
>i['prop1'] : string | number
>i : One & Two
>'prop1' : "prop1"
>"hello" : "hello"
const iv2 = i['prop2'];
>iv2 : string
>i['prop2'] : string
>i : One & Two
>'prop2' : "prop2"
i['prop2'] = 42;
>i['prop2'] = 42 : 42
>i['prop2'] : string
>i : One & Two
>'prop2' : "prop2"
>42 : 42
i['prop2'] = "hello";
>i['prop2'] = "hello" : "hello"
>i['prop2'] : string
>i : One & Two
>'prop2' : "prop2"
>"hello" : "hello"
class Three {
>Three : Three
get prop1(): string {
>prop1 : string
return "";
>"" : ""
}
set prop1(s: string | number) {}
>prop1 : string
>s : string | number
prop2: number = 42;
>prop2 : number
>42 : 42
}
class Four {
>Four : Four
get prop1(): "hello" {
>prop1 : "hello"
return "hello";
>"hello" : "hello"
}
set prop1(s: "hello" | number) {}
>prop1 : "hello"
>s : number | "hello"
get prop2(): string {
>prop2 : string
return "";
>"" : ""
}
set prop2(s: string | 42) {}
>prop2 : string
>s : string | 42
}
class Five {
>Five : Five
get prop1(): "hello" {
>prop1 : "hello"
return "hello";
>"hello" : "hello"
}
set prop1(s: "hello" | boolean) {}
>prop1 : "hello"
>s : boolean | "hello"
get prop2(): string {
>prop2 : string
return "";
>"" : ""
}
set prop2(s: string | number | boolean) {}
>prop2 : string
>s : string | number | boolean
}
declare const i2: Three & Four & Five;
>i2 : Three & Four & Five
i2['prop1'] = 42;
>i2['prop1'] = 42 : 42
>i2['prop1'] : "hello"
>i2 : Three & Four & Five
>'prop1' : "prop1"
>42 : 42
i2['prop1'] = "hello";
>i2['prop1'] = "hello" : "hello"
>i2['prop1'] : "hello"
>i2 : Three & Four & Five
>'prop1' : "prop1"
>"hello" : "hello"
i2['prop2'] = 42;
>i2['prop2'] = 42 : 42
>i2['prop2'] : 42
>i2 : Three & Four & Five
>'prop2' : "prop2"
>42 : 42
i2['prop2'] = "hello";
>i2['prop2'] = "hello" : "hello"
>i2['prop2'] : 42
>i2 : Three & Four & Five
>'prop2' : "prop2"
>"hello" : "hello"
class Six {
>Six : Six
get prop1(): boolean | number {
>prop1 : number | boolean
return 42;
>42 : 42
}
set prop1(s: boolean | string) {}
>prop1 : number | boolean
>s : string | boolean
get prop2(): bigint | number {
>prop2 : number | bigint
return 10;
>10 : 10
}
set prop2(s: boolean | null) {}
>prop2 : number | bigint
>s : boolean | null
}
declare const s1: Six
>s1 : Six
declare const k1: 'prop1' | 'prop2'
>k1 : "prop1" | "prop2"
const sv1 = s1[k1]
>sv1 : number | bigint | boolean
>s1[k1] : number | bigint | boolean
>s1 : Six
>k1 : "prop1" | "prop2"
s1[k1] = 42
>s1[k1] = 42 : 42
>s1[k1] : boolean
>s1 : Six
>k1 : "prop1" | "prop2"
>42 : 42
s1[k1] = true
>s1[k1] = true : true
>s1[k1] : boolean
>s1 : Six
>k1 : "prop1" | "prop2"
>true : true
s1[k1] = ''
>s1[k1] = '' : ""
>s1[k1] : boolean
>s1 : Six
>k1 : "prop1" | "prop2"
>'' : ""
s1[k1] = null
>s1[k1] = null : null
>s1[k1] : boolean
>s1 : Six
>k1 : "prop1" | "prop2"

View File

@ -6,12 +6,12 @@ class Test<S> {
get value(): string {
return null!;
}
// -- Replacing the getter such that the getter/setter types match, removes the error:
// get value(): string | ((item: S) => string) {
// return null!;
// }
// -- Or, replacing the setter such that a concrete type is used, removes the error:
// set value(value: string | ((item: { property: string }) => string)) {}
}
@ -21,3 +21,4 @@ const a = new Test<{
}>();
a.value = (item) => item.property
a['value'] = (item) => item.property

View File

@ -0,0 +1,153 @@
// @strict: true
// @lib: esnext, dom
// @noEmit: true
export {}
interface Serializer {
set value(v: string | number | boolean);
get value(): string;
}
declare let box: Serializer;
const v = box['value']
box['value'] = true;
box['value'] = 42;
box['value'] = "hello";
interface Element {
get style(): CSSStyleDeclaration;
set style(cssText: string);
}
declare const element: Element;
element['style'] = "color: red";
element['style'] = element.style;
class One {
get prop1(): string {
return "";
}
set prop1(s: string | number) {}
get prop2(): string {
return "";
}
set prop2(s: string | number) {}
prop3: number = 42;
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;
declare const i: One & Two;
const iv1 = i['prop1'];
i['prop1'] = 42;
i['prop1'] = "hello";
const iv2 = i['prop2'];
i['prop2'] = 42;
i['prop2'] = "hello";
class Three {
get prop1(): string {
return "";
}
set prop1(s: string | number) {}
prop2: number = 42;
}
class Four {
get prop1(): "hello" {
return "hello";
}
set prop1(s: "hello" | number) {}
get prop2(): string {
return "";
}
set prop2(s: string | 42) {}
}
class Five {
get prop1(): "hello" {
return "hello";
}
set prop1(s: "hello" | boolean) {}
get prop2(): string {
return "";
}
set prop2(s: string | number | boolean) {}
}
declare const i2: Three & Four & Five;
i2['prop1'] = 42;
i2['prop1'] = "hello";
i2['prop2'] = 42;
i2['prop2'] = "hello";
class Six {
get prop1(): boolean | number {
return 42;
}
set prop1(s: boolean | string) {}
get prop2(): bigint | number {
return 10;
}
set prop2(s: boolean | null) {}
}
declare const s1: Six
declare const k1: 'prop1' | 'prop2'
const sv1 = s1[k1]
s1[k1] = 42
s1[k1] = true
s1[k1] = ''
s1[k1] = null

View File

@ -0,0 +1,8 @@
/// <reference path='fourslash.ts'/>
// @strict: true
// @exactOptionalPropertyTypes: true
//// declare const xx: { prop?: number };
//// xx['prop'/*1*/] = 1;
verify.quickInfoAt('1', '(property) prop?: number');

View File

@ -0,0 +1,8 @@
/// <reference path='fourslash.ts'/>
// @strict: true
// @exactOptionalPropertyTypes: true
//// declare const xx: { prop?: number };
//// xx['prop'/*1*/] += 1;
verify.quickInfoAt('1', '(property) prop?: number');

View File

@ -0,0 +1,8 @@
/// <reference path='fourslash.ts'/>
// @strict: true
// @exactOptionalPropertyTypes: true
//// declare const xx: { prop?: number };
//// xx['prop'/*1*/] ??= 1;
verify.quickInfoAt('1', '(property) prop?: number');

View File

@ -0,0 +1,11 @@
/// <reference path='fourslash.ts'/>
// @strict: true
//// interface Serializer {
//// set value(v: string | number | boolean);
//// get value(): string;
//// }
//// declare let box: Serializer;
//// box['value'/*1*/] = true;
verify.quickInfoAt('1', '(property) Serializer.value: string | number | boolean');

View File

@ -0,0 +1,11 @@
/// <reference path='fourslash.ts'/>
// @strict: true
//// interface Serializer {
//// set value(v: string | number);
//// get value(): string;
//// }
//// declare let box: Serializer;
//// box['value'/*1*/] += 10;
verify.quickInfoAt('1', '(property) Serializer.value: string | number');