Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow getter and setter types to be unrelated #53417

Merged
merged 2 commits into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38507,12 +38507,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
error(getter.name, Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter);
error(setter.name, Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter);
}

const getterType = getAnnotatedAccessorType(getter);
const setterType = getAnnotatedAccessorType(setter);
if (getterType && setterType) {
checkTypeAssignableTo(getterType, setterType, getter, Diagnostics.The_return_type_of_a_get_accessor_must_be_assignable_to_its_set_accessor_type);
}
}
}
const returnType = getTypeOfAccessors(getSymbolOfDeclaration(node));
Expand Down
4 changes: 0 additions & 4 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1972,10 +1972,6 @@
"category": "Error",
"code": 2379
},
"The return type of a 'get' accessor must be assignable to its 'set' accessor type": {
"category": "Error",
"code": 2380
},
"Overload signatures must all be exported or non-exported.": {
"category": "Error",
"code": 2383
Expand Down
7 changes: 2 additions & 5 deletions tests/baselines/reference/abstractPropertyNegative.errors.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
tests/cases/compiler/abstractPropertyNegative.ts(10,18): error TS2380: The return type of a 'get' accessor must be assignable to its 'set' accessor type
tests/cases/compiler/abstractPropertyNegative.ts(13,7): error TS18052: Non-abstract class 'C' does not implement all abstract members of 'B'
tests/cases/compiler/abstractPropertyNegative.ts(15,5): error TS1253: Abstract properties can only appear within an abstract class.
tests/cases/compiler/abstractPropertyNegative.ts(16,37): error TS1005: '{' expected.
Expand All @@ -15,7 +14,7 @@ tests/cases/compiler/abstractPropertyNegative.ts(40,9): error TS2676: Accessors
tests/cases/compiler/abstractPropertyNegative.ts(41,18): error TS2676: Accessors must both be abstract or non-abstract.


==== tests/cases/compiler/abstractPropertyNegative.ts (12 errors) ====
==== tests/cases/compiler/abstractPropertyNegative.ts (11 errors) ====
interface A {
prop: string;
m(): string;
Expand All @@ -26,9 +25,7 @@ tests/cases/compiler/abstractPropertyNegative.ts(41,18): error TS2676: Accessors
abstract get readonlyProp(): string;
abstract m(): string;
abstract get mismatch(): string;
~~~~~~~~
!!! error TS2380: The return type of a 'get' accessor must be assignable to its 'set' accessor type
abstract set mismatch(val: number); // error, not same type
abstract set mismatch(val: number);
}
class C extends B {
~
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/abstractPropertyNegative.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ abstract class B implements A {
abstract get readonlyProp(): string;
abstract m(): string;
abstract get mismatch(): string;
abstract set mismatch(val: number); // error, not same type
abstract set mismatch(val: number);
}
class C extends B {
readonly ro = "readonly please";
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/abstractPropertyNegative.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ abstract class B implements A {
abstract get mismatch(): string;
>mismatch : Symbol(B.mismatch, Decl(abstractPropertyNegative.ts, 8, 25), Decl(abstractPropertyNegative.ts, 9, 36))

abstract set mismatch(val: number); // error, not same type
abstract set mismatch(val: number);
>mismatch : Symbol(B.mismatch, Decl(abstractPropertyNegative.ts, 8, 25), Decl(abstractPropertyNegative.ts, 9, 36))
>val : Symbol(val, Decl(abstractPropertyNegative.ts, 10, 26))
}
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/abstractPropertyNegative.types
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ abstract class B implements A {
abstract get mismatch(): string;
>mismatch : string

abstract set mismatch(val: number); // error, not same type
abstract set mismatch(val: number);
>mismatch : string
>val : number
}
Expand Down
50 changes: 50 additions & 0 deletions tests/baselines/reference/divergentAccessorsTypes6.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
tests/cases/compiler/divergentAccessorsTypes6.ts(11,1): error TS2322: Type 'CSSStyleDeclaration' is not assignable to type 'string'.
tests/cases/compiler/divergentAccessorsTypes6.ts(19,23): error TS2344: Type 'string' does not satisfy the constraint 'never'.
tests/cases/compiler/divergentAccessorsTypes6.ts(23,23): error TS2344: Type 'string' does not satisfy the constraint 'never'.
tests/cases/compiler/divergentAccessorsTypes6.ts(29,16): error TS2322: Type 'number' is not assignable to type 'string'.


==== tests/cases/compiler/divergentAccessorsTypes6.ts (4 errors) ====
export {};

interface Element {
get style(): CSSStyleDeclaration;
set style(cssText: string);
}

declare const element: Element;
element.style = "color: red";
element.style.animationTimingFunction;
element.style = element.style; // error
~~~~~~~~~~~~~
!!! error TS2322: Type 'CSSStyleDeclaration' is not assignable to type 'string'.

// Now that we don't check for getter/setter assignability, we should
// ensure the setter annotation is actually checked even if it's never observed.

type Fail<T extends never> = T;
interface I1 {
get x(): number;
set x(value: Fail<string>);
~~~~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'never'.
}
const o1 = {
get x(): number { return 0; },
set x(value: Fail<string>) {}
~~~~~~
!!! error TS2344: Type 'string' does not satisfy the constraint 'never'.
}

// A setter annotation still implies the getter return type.

const o2 = {
get p1() { return 0; }, // error - no annotation means type is implied from the setter annotation
~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
set p1(value: string) {},

get p2(): number { return 0; }, // ok - explicit annotation
set p2(value: string) {},
};

58 changes: 58 additions & 0 deletions tests/baselines/reference/divergentAccessorsTypes6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//// [divergentAccessorsTypes6.ts]
export {};

interface Element {
get style(): CSSStyleDeclaration;
set style(cssText: string);
}

declare const element: Element;
element.style = "color: red";
element.style.animationTimingFunction;
element.style = element.style; // error

// Now that we don't check for getter/setter assignability, we should
// ensure the setter annotation is actually checked even if it's never observed.

type Fail<T extends never> = T;
interface I1 {
get x(): number;
set x(value: Fail<string>);
}
const o1 = {
get x(): number { return 0; },
set x(value: Fail<string>) {}
}

// A setter annotation still implies the getter return type.

const o2 = {
get p1() { return 0; }, // error - no annotation means type is implied from the setter annotation
set p1(value: string) {},

get p2(): number { return 0; }, // ok - explicit annotation
set p2(value: string) {},
};


//// [divergentAccessorsTypes6.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
element.style = "color: red";
element.style.animationTimingFunction;
element.style = element.style; // error
var o1 = {
get x() { return 0; },
set x(value) { }
};
// A setter annotation still implies the getter return type.
var o2 = {
get p1() { return 0; },
set p1(value) { },
get p2() { return 0; },
set p2(value) { },
};


//// [divergentAccessorsTypes6.d.ts]
export {};
91 changes: 91 additions & 0 deletions tests/baselines/reference/divergentAccessorsTypes6.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
=== tests/cases/compiler/divergentAccessorsTypes6.ts ===
export {};

interface Element {
>Element : Symbol(Element, Decl(divergentAccessorsTypes6.ts, 0, 10))

get style(): CSSStyleDeclaration;
>style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))
>CSSStyleDeclaration : Symbol(CSSStyleDeclaration, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))

set style(cssText: string);
>style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))
>cssText : Symbol(cssText, Decl(divergentAccessorsTypes6.ts, 4, 14))
}

declare const element: Element;
>element : Symbol(element, Decl(divergentAccessorsTypes6.ts, 7, 13))
>Element : Symbol(Element, Decl(divergentAccessorsTypes6.ts, 0, 10))

element.style = "color: red";
>element.style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))
>element : Symbol(element, Decl(divergentAccessorsTypes6.ts, 7, 13))
>style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))

element.style.animationTimingFunction;
>element.style.animationTimingFunction : Symbol(CSSStyleDeclaration.animationTimingFunction, Decl(lib.dom.d.ts, --, --))
>element.style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))
>element : Symbol(element, Decl(divergentAccessorsTypes6.ts, 7, 13))
>style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))
>animationTimingFunction : Symbol(CSSStyleDeclaration.animationTimingFunction, Decl(lib.dom.d.ts, --, --))

element.style = element.style; // error
>element.style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))
>element : Symbol(element, Decl(divergentAccessorsTypes6.ts, 7, 13))
>style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))
>element.style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))
>element : Symbol(element, Decl(divergentAccessorsTypes6.ts, 7, 13))
>style : Symbol(Element.style, Decl(divergentAccessorsTypes6.ts, 2, 19), Decl(divergentAccessorsTypes6.ts, 3, 37))

// Now that we don't check for getter/setter assignability, we should
// ensure the setter annotation is actually checked even if it's never observed.

type Fail<T extends never> = T;
>Fail : Symbol(Fail, Decl(divergentAccessorsTypes6.ts, 10, 30))
>T : Symbol(T, Decl(divergentAccessorsTypes6.ts, 15, 10))
>T : Symbol(T, Decl(divergentAccessorsTypes6.ts, 15, 10))

interface I1 {
>I1 : Symbol(I1, Decl(divergentAccessorsTypes6.ts, 15, 31))

get x(): number;
>x : Symbol(I1.x, Decl(divergentAccessorsTypes6.ts, 16, 14), Decl(divergentAccessorsTypes6.ts, 17, 20))

set x(value: Fail<string>);
>x : Symbol(I1.x, Decl(divergentAccessorsTypes6.ts, 16, 14), Decl(divergentAccessorsTypes6.ts, 17, 20))
>value : Symbol(value, Decl(divergentAccessorsTypes6.ts, 18, 10))
>Fail : Symbol(Fail, Decl(divergentAccessorsTypes6.ts, 10, 30))
}
const o1 = {
>o1 : Symbol(o1, Decl(divergentAccessorsTypes6.ts, 20, 5))

get x(): number { return 0; },
>x : Symbol(x, Decl(divergentAccessorsTypes6.ts, 20, 12), Decl(divergentAccessorsTypes6.ts, 21, 34))

set x(value: Fail<string>) {}
>x : Symbol(x, Decl(divergentAccessorsTypes6.ts, 20, 12), Decl(divergentAccessorsTypes6.ts, 21, 34))
>value : Symbol(value, Decl(divergentAccessorsTypes6.ts, 22, 10))
>Fail : Symbol(Fail, Decl(divergentAccessorsTypes6.ts, 10, 30))
}

// A setter annotation still implies the getter return type.

const o2 = {
>o2 : Symbol(o2, Decl(divergentAccessorsTypes6.ts, 27, 5))

get p1() { return 0; }, // error - no annotation means type is implied from the setter annotation
>p1 : Symbol(p1, Decl(divergentAccessorsTypes6.ts, 27, 12), Decl(divergentAccessorsTypes6.ts, 28, 27))

set p1(value: string) {},
>p1 : Symbol(p1, Decl(divergentAccessorsTypes6.ts, 27, 12), Decl(divergentAccessorsTypes6.ts, 28, 27))
>value : Symbol(value, Decl(divergentAccessorsTypes6.ts, 29, 11))

get p2(): number { return 0; }, // ok - explicit annotation
>p2 : Symbol(p2, Decl(divergentAccessorsTypes6.ts, 29, 29), Decl(divergentAccessorsTypes6.ts, 31, 35))

set p2(value: string) {},
>p2 : Symbol(p2, Decl(divergentAccessorsTypes6.ts, 29, 29), Decl(divergentAccessorsTypes6.ts, 31, 35))
>value : Symbol(value, Decl(divergentAccessorsTypes6.ts, 32, 11))

};

89 changes: 89 additions & 0 deletions tests/baselines/reference/divergentAccessorsTypes6.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
=== tests/cases/compiler/divergentAccessorsTypes6.ts ===
export {};

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 : string
>"color: red" : "color: red"

element.style.animationTimingFunction;
>element.style.animationTimingFunction : string
>element.style : CSSStyleDeclaration
>element : Element
>style : CSSStyleDeclaration
>animationTimingFunction : string

element.style = element.style; // error
>element.style = element.style : CSSStyleDeclaration
>element.style : string
>element : Element
>style : string
>element.style : CSSStyleDeclaration
>element : Element
>style : CSSStyleDeclaration

// Now that we don't check for getter/setter assignability, we should
// ensure the setter annotation is actually checked even if it's never observed.

type Fail<T extends never> = T;
>Fail : T

interface I1 {
get x(): number;
>x : number

set x(value: Fail<string>);
>x : number
>value : string
}
const o1 = {
>o1 : { x: number; }
>{ get x(): number { return 0; }, set x(value: Fail<string>) {}} : { x: number; }

get x(): number { return 0; },
>x : number
>0 : 0

set x(value: Fail<string>) {}
>x : number
>value : string
}

// A setter annotation still implies the getter return type.

const o2 = {
>o2 : { p1: string; p2: number; }
>{ get p1() { return 0; }, // error - no annotation means type is implied from the setter annotation set p1(value: string) {}, get p2(): number { return 0; }, // ok - explicit annotation set p2(value: string) {},} : { p1: string; p2: number; }

get p1() { return 0; }, // error - no annotation means type is implied from the setter annotation
>p1 : string
>0 : 0

set p1(value: string) {},
>p1 : string
>value : string

get p2(): number { return 0; }, // ok - explicit annotation
>p2 : number
>0 : 0

set p2(value: string) {},
>p2 : number
>value : string

};

12 changes: 0 additions & 12 deletions tests/baselines/reference/getAndSetNotIdenticalType.errors.txt

This file was deleted.

Loading