Skip to content

Commit 7e73fef

Browse files
committed
Treat void-typed properties as optional
1 parent 3e824f1 commit 7e73fef

20 files changed

+751
-74
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,18 @@ namespace ts {
13521352
}
13531353
}
13541354

1355+
/**
1356+
* Attempts to return the `SymbolLinks` for `symbol`, if one already exists.
1357+
* Does not allocate a symbol id or a `SymbolLinks` if it doesn't already exists.
1358+
*/
1359+
function tryGetSymbolLinks(symbol: Symbol): SymbolLinks | undefined {
1360+
if (symbol.flags & SymbolFlags.Transient) return <TransientSymbol>symbol;
1361+
return symbol.id ? symbolLinks[symbol.id] : undefined;
1362+
}
1363+
1364+
/**
1365+
* Gets or creates a `SymbolLinks` for `symbol`.
1366+
*/
13551367
function getSymbolLinks(symbol: Symbol): SymbolLinks {
13561368
if (symbol.flags & SymbolFlags.Transient) return <TransientSymbol>symbol;
13571369
const id = getSymbolId(symbol);
@@ -7666,11 +7678,11 @@ namespace ts {
76667678
function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean {
76677679
switch (propertyName) {
76687680
case TypeSystemPropertyName.Type:
7669-
return !!getSymbolLinks(<Symbol>target).type;
7681+
return !!tryGetSymbolLinks(<Symbol>target)?.type;
76707682
case TypeSystemPropertyName.EnumTagType:
76717683
return !!(getNodeLinks(target as JSDocEnumTag).resolvedEnumType);
76727684
case TypeSystemPropertyName.DeclaredType:
7673-
return !!getSymbolLinks(<Symbol>target).declaredType;
7685+
return !!tryGetSymbolLinks(<Symbol>target)?.declaredType;
76747686
case TypeSystemPropertyName.ResolvedBaseConstructorType:
76757687
return !!(<InterfaceType>target).resolvedBaseConstructorType;
76767688
case TypeSystemPropertyName.ResolvedReturnType:
@@ -8509,6 +8521,14 @@ namespace ts {
85098521
return links.type;
85108522
}
85118523

8524+
function isOptionalProperty(prop: Symbol) {
8525+
if (prop.flags & SymbolFlags.Optional) return true;
8526+
// We don't use `getTypeOfSymbol` here as we may be in the middle of resolving the type for `prop` and
8527+
// we shouldn't re-enter to check for `void`.
8528+
const type = tryGetSymbolLinks(prop)?.type;
8529+
return !!(type && forEachType(type, acceptsVoid));
8530+
}
8531+
85128532
function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol) {
85138533
// Handle prototype property
85148534
if (symbol.flags & SymbolFlags.Prototype) {
@@ -17894,7 +17914,7 @@ namespace ts {
1789417914
return Ternary.False;
1789517915
}
1789617916
// When checking for comparability, be more lenient with optional properties.
17897-
if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
17917+
if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !isOptionalProperty(targetProp)) {
1789817918
// TypeScript 1.0 spec (April 2014): 3.8.3
1789917919
// S is a subtype of a type T, and T is a supertype of S if ...
1790017920
// S' and T are object types and, for each member M in T..
@@ -19709,7 +19729,7 @@ namespace ts {
1970919729
if (isStaticPrivateIdentifierProperty(targetProp)) {
1971019730
continue;
1971119731
}
19712-
if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional || getCheckFlags(targetProp) & CheckFlags.Partial)) {
19732+
if (requireOptionalProperties || !((getCheckFlags(targetProp) & CheckFlags.Partial) || isOptionalProperty(targetProp))) {
1971319733
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
1971419734
if (!sourceProp) {
1971519735
yield targetProp;

tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import(
2222
[e: string]: {};
2323
}
2424
interface Element {
25-
__domBrand: void;
25+
__domBrand: never;
2626
props: {
2727
children?: Element[];
2828
};
@@ -42,7 +42,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import(
4242
[e: string]: {};
4343
}
4444
interface Element {
45-
__predomBrand: void;
45+
__predomBrand: never;
4646
props: {
4747
children?: Element[];
4848
};
@@ -66,7 +66,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import(
6666
!!! error TS2532: Object is possibly 'undefined'.
6767

6868
export class MyClass implements predom.JSX.Element {
69-
__predomBrand!: void;
69+
__predomBrand!: never;
7070
constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {}
7171
render() {
7272
return <p>
@@ -92,7 +92,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import(
9292
const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{props.children}</p>;
9393

9494
class DOMClass implements dom.JSX.Element {
95-
__domBrand!: void;
95+
__domBrand!: never;
9696
constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}
9797
render() {
9898
return <p>{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}</p>;

tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export namespace dom {
77
[e: string]: {};
88
}
99
interface Element {
10-
__domBrand: void;
10+
__domBrand: never;
1111
props: {
1212
children?: Element[];
1313
};
@@ -27,7 +27,7 @@ export namespace predom {
2727
[e: string]: {};
2828
}
2929
interface Element {
30-
__predomBrand: void;
30+
__predomBrand: never;
3131
props: {
3232
children?: Element[];
3333
};
@@ -47,7 +47,7 @@ import { predom } from "./renderer2"
4747
export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{...this.props.children}</p>;
4848

4949
export class MyClass implements predom.JSX.Element {
50-
__predomBrand!: void;
50+
__predomBrand!: never;
5151
constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {}
5252
render() {
5353
return <p>
@@ -70,7 +70,7 @@ elem = <h></h>; // Expect assignability error here
7070
const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{props.children}</p>;
7171

7272
class DOMClass implements dom.JSX.Element {
73-
__domBrand!: void;
73+
__domBrand!: never;
7474
constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}
7575
render() {
7676
return <p>{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}</p>;

tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.symbols

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ export namespace dom {
1414
interface Element {
1515
>Element : Symbol(Element, Decl(renderer.d.ts, 4, 9))
1616

17-
__domBrand: void;
17+
__domBrand: never;
1818
>__domBrand : Symbol(Element.__domBrand, Decl(renderer.d.ts, 5, 27))
1919

2020
props: {
21-
>props : Symbol(Element.props, Decl(renderer.d.ts, 6, 29))
21+
>props : Symbol(Element.props, Decl(renderer.d.ts, 6, 30))
2222

2323
children?: Element[];
2424
>children : Symbol(children, Decl(renderer.d.ts, 7, 20))
@@ -65,11 +65,11 @@ export namespace predom {
6565
interface Element {
6666
>Element : Symbol(Element, Decl(renderer2.d.ts, 4, 9))
6767

68-
__predomBrand: void;
68+
__predomBrand: never;
6969
>__predomBrand : Symbol(Element.__predomBrand, Decl(renderer2.d.ts, 5, 27))
7070

7171
props: {
72-
>props : Symbol(Element.props, Decl(renderer2.d.ts, 6, 32))
72+
>props : Symbol(Element.props, Decl(renderer2.d.ts, 6, 33))
7373

7474
children?: Element[];
7575
>children : Symbol(children, Decl(renderer2.d.ts, 7, 20))
@@ -137,7 +137,7 @@ export class MyClass implements predom.JSX.Element {
137137
>JSX : Symbol(predom.JSX, Decl(renderer2.d.ts, 0, 25))
138138
>Element : Symbol(predom.JSX.Element, Decl(renderer2.d.ts, 4, 9))
139139

140-
__predomBrand!: void;
140+
__predomBrand!: never;
141141
>__predomBrand : Symbol(MyClass.__predomBrand, Decl(component.tsx, 5, 52))
142142

143143
constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {}
@@ -260,7 +260,7 @@ class DOMClass implements dom.JSX.Element {
260260
>JSX : Symbol(dom.JSX, Decl(renderer.d.ts, 0, 22))
261261
>Element : Symbol(dom.JSX.Element, Decl(renderer.d.ts, 4, 9))
262262

263-
__domBrand!: void;
263+
__domBrand!: never;
264264
>__domBrand : Symbol(DOMClass.__domBrand, Decl(index.tsx, 8, 43))
265265

266266
constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}

tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.types

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ export namespace dom {
66
>e : string
77
}
88
interface Element {
9-
__domBrand: void;
10-
>__domBrand : void
9+
__domBrand: never;
10+
>__domBrand : never
1111

1212
props: {
1313
>props : { children?: Element[]; }
@@ -41,8 +41,8 @@ export namespace predom {
4141
>e : string
4242
}
4343
interface Element {
44-
__predomBrand: void;
45-
>__predomBrand : void
44+
__predomBrand: never;
45+
>__predomBrand : never
4646

4747
props: {
4848
>props : { children?: Element[]; }
@@ -110,8 +110,8 @@ export class MyClass implements predom.JSX.Element {
110110
>predom : () => predom.JSX.Element
111111
>JSX : any
112112

113-
__predomBrand!: void;
114-
>__predomBrand : void
113+
__predomBrand!: never;
114+
>__predomBrand : never
115115

116116
constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {}
117117
>props : { x: number; y: number; children?: predom.JSX.Element[]; }
@@ -246,8 +246,8 @@ class DOMClass implements dom.JSX.Element {
246246
>dom : () => dom.JSX.Element
247247
>JSX : any
248248

249-
__domBrand!: void;
250-
>__domBrand : void
249+
__domBrand!: never;
250+
>__domBrand : never
251251

252252
constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}
253253
>props : { x: number; y: number; children?: dom.JSX.Element[]; }

tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__pre
88
[e: string]: {};
99
}
1010
interface Element {
11-
__domBrand: void;
11+
__domBrand: never;
1212
children: Element[];
1313
props: {};
1414
}
@@ -24,7 +24,7 @@ tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__pre
2424
[e: string]: {};
2525
}
2626
interface Element {
27-
__predomBrand: void;
27+
__predomBrand: never;
2828
children: Element[];
2929
props: {};
3030
}

tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ declare global {
77
[e: string]: {};
88
}
99
interface Element {
10-
__domBrand: void;
10+
__domBrand: never;
1111
children: Element[];
1212
props: {};
1313
}
@@ -23,7 +23,7 @@ export namespace predom {
2323
[e: string]: {};
2424
}
2525
interface Element {
26-
__predomBrand: void;
26+
__predomBrand: never;
2727
children: Element[];
2828
props: {};
2929
}

tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.symbols

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ declare global {
1414
interface Element {
1515
>Element : Symbol(Element, Decl(renderer.d.ts, 4, 9))
1616

17-
__domBrand: void;
17+
__domBrand: never;
1818
>__domBrand : Symbol(Element.__domBrand, Decl(renderer.d.ts, 5, 27))
1919

2020
children: Element[];
21-
>children : Symbol(Element.children, Decl(renderer.d.ts, 6, 29))
21+
>children : Symbol(Element.children, Decl(renderer.d.ts, 6, 30))
2222
>Element : Symbol(Element, Decl(renderer.d.ts, 4, 9))
2323

2424
props: {};
@@ -54,11 +54,11 @@ export namespace predom {
5454
interface Element {
5555
>Element : Symbol(Element, Decl(renderer2.d.ts, 4, 9))
5656

57-
__predomBrand: void;
57+
__predomBrand: never;
5858
>__predomBrand : Symbol(Element.__predomBrand, Decl(renderer2.d.ts, 5, 27))
5959

6060
children: Element[];
61-
>children : Symbol(Element.children, Decl(renderer2.d.ts, 6, 32))
61+
>children : Symbol(Element.children, Decl(renderer2.d.ts, 6, 33))
6262
>Element : Symbol(Element, Decl(renderer2.d.ts, 4, 9))
6363

6464
props: {};

tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ declare global {
88
>e : string
99
}
1010
interface Element {
11-
__domBrand: void;
12-
>__domBrand : void
11+
__domBrand: never;
12+
>__domBrand : never
1313

1414
children: Element[];
1515
>children : Element[]
@@ -36,8 +36,8 @@ export namespace predom {
3636
>e : string
3737
}
3838
interface Element {
39-
__predomBrand: void;
40-
>__predomBrand : void
39+
__predomBrand: never;
40+
>__predomBrand : never
4141

4242
children: Element[];
4343
>children : Element[]

tests/baselines/reference/strictFunctionTypesErrors.errors.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,9 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(155,5): error TS2322: Type '(c
264264
i4 = i2; // Ok
265265
i4 = i3; // Ok
266266

267-
interface Animal { animal: void }
268-
interface Dog extends Animal { dog: void }
269-
interface Cat extends Animal { cat: void }
267+
interface Animal { animal: never }
268+
interface Dog extends Animal { dog: never }
269+
interface Cat extends Animal { cat: never }
270270

271271
interface Comparer1<T> {
272272
compare(a: T, b: T): number;

tests/baselines/reference/strictFunctionTypesErrors.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ i4 = i1; // Ok
8888
i4 = i2; // Ok
8989
i4 = i3; // Ok
9090

91-
interface Animal { animal: void }
92-
interface Dog extends Animal { dog: void }
93-
interface Cat extends Animal { cat: void }
91+
interface Animal { animal: never }
92+
interface Dog extends Animal { dog: never }
93+
interface Cat extends Animal { cat: never }
9494

9595
interface Comparer1<T> {
9696
compare(a: T, b: T): number;

0 commit comments

Comments
 (0)