diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5658109668c2c..8a4ca8372d73d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1352,6 +1352,18 @@ namespace ts { } } + /** + * Attempts to return the `SymbolLinks` for `symbol`, if one already exists. + * Does not allocate a symbol id or a `SymbolLinks` if it doesn't already exists. + */ + function tryGetSymbolLinks(symbol: Symbol): SymbolLinks | undefined { + if (symbol.flags & SymbolFlags.Transient) return symbol; + return symbol.id ? symbolLinks[symbol.id] : undefined; + } + + /** + * Gets or creates a `SymbolLinks` for `symbol`. + */ function getSymbolLinks(symbol: Symbol): SymbolLinks { if (symbol.flags & SymbolFlags.Transient) return symbol; const id = getSymbolId(symbol); @@ -7666,11 +7678,11 @@ namespace ts { function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean { switch (propertyName) { case TypeSystemPropertyName.Type: - return !!getSymbolLinks(target).type; + return !!tryGetSymbolLinks(target)?.type; case TypeSystemPropertyName.EnumTagType: return !!(getNodeLinks(target as JSDocEnumTag).resolvedEnumType); case TypeSystemPropertyName.DeclaredType: - return !!getSymbolLinks(target).declaredType; + return !!tryGetSymbolLinks(target)?.declaredType; case TypeSystemPropertyName.ResolvedBaseConstructorType: return !!(target).resolvedBaseConstructorType; case TypeSystemPropertyName.ResolvedReturnType: @@ -8509,6 +8521,14 @@ namespace ts { return links.type; } + function isOptionalProperty(prop: Symbol) { + if (prop.flags & SymbolFlags.Optional) return true; + // We don't use `getTypeOfSymbol` here as we may be in the middle of resolving the type for `prop` and + // we shouldn't re-enter to check for `void`. + const type = tryGetSymbolLinks(prop)?.type; + return !!(type && forEachType(type, acceptsVoid)); + } + function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol) { // Handle prototype property if (symbol.flags & SymbolFlags.Prototype) { @@ -17894,7 +17914,7 @@ namespace ts { return Ternary.False; } // When checking for comparability, be more lenient with optional properties. - if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) { + if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !isOptionalProperty(targetProp)) { // TypeScript 1.0 spec (April 2014): 3.8.3 // S is a subtype of a type T, and T is a supertype of S if ... // S' and T are object types and, for each member M in T.. @@ -19709,7 +19729,7 @@ namespace ts { if (isStaticPrivateIdentifierProperty(targetProp)) { continue; } - if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional || getCheckFlags(targetProp) & CheckFlags.Partial)) { + if (requireOptionalProperties || !((getCheckFlags(targetProp) & CheckFlags.Partial) || isOptionalProperty(targetProp))) { const sourceProp = getPropertyOfType(source, targetProp.escapedName); if (!sourceProp) { yield targetProp; diff --git a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt index caced97b3e8bf..600d649ab1529 100644 --- a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt +++ b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt @@ -22,7 +22,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import( [e: string]: {}; } interface Element { - __domBrand: void; + __domBrand: never; props: { children?: Element[]; }; @@ -42,7 +42,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import( [e: string]: {}; } interface Element { - __predomBrand: void; + __predomBrand: never; props: { children?: Element[]; }; @@ -66,7 +66,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import( !!! error TS2532: Object is possibly 'undefined'. export class MyClass implements predom.JSX.Element { - __predomBrand!: void; + __predomBrand!: never; constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {} render() { return

@@ -92,7 +92,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import( const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) =>

{props.x} + {props.y} = {props.x + props.y}{props.children}

; class DOMClass implements dom.JSX.Element { - __domBrand!: void; + __domBrand!: never; constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {} render() { return

{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}

; diff --git a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.js b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.js index 7b29740e7f9d6..04f661d489d4c 100644 --- a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.js +++ b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.js @@ -7,7 +7,7 @@ export namespace dom { [e: string]: {}; } interface Element { - __domBrand: void; + __domBrand: never; props: { children?: Element[]; }; @@ -27,7 +27,7 @@ export namespace predom { [e: string]: {}; } interface Element { - __predomBrand: void; + __predomBrand: never; props: { children?: Element[]; }; @@ -47,7 +47,7 @@ import { predom } from "./renderer2" export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) =>

{props.x} + {props.y} = {props.x + props.y}{...this.props.children}

; export class MyClass implements predom.JSX.Element { - __predomBrand!: void; + __predomBrand!: never; constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {} render() { return

@@ -70,7 +70,7 @@ elem = ; // Expect assignability error here const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) =>

{props.x} + {props.y} = {props.x + props.y}{props.children}

; class DOMClass implements dom.JSX.Element { - __domBrand!: void; + __domBrand!: never; constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {} render() { return

{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}

; diff --git a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.symbols b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.symbols index 25af733e40f35..9a446ebe9b81e 100644 --- a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.symbols +++ b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.symbols @@ -14,11 +14,11 @@ export namespace dom { interface Element { >Element : Symbol(Element, Decl(renderer.d.ts, 4, 9)) - __domBrand: void; + __domBrand: never; >__domBrand : Symbol(Element.__domBrand, Decl(renderer.d.ts, 5, 27)) props: { ->props : Symbol(Element.props, Decl(renderer.d.ts, 6, 29)) +>props : Symbol(Element.props, Decl(renderer.d.ts, 6, 30)) children?: Element[]; >children : Symbol(children, Decl(renderer.d.ts, 7, 20)) @@ -65,11 +65,11 @@ export namespace predom { interface Element { >Element : Symbol(Element, Decl(renderer2.d.ts, 4, 9)) - __predomBrand: void; + __predomBrand: never; >__predomBrand : Symbol(Element.__predomBrand, Decl(renderer2.d.ts, 5, 27)) props: { ->props : Symbol(Element.props, Decl(renderer2.d.ts, 6, 32)) +>props : Symbol(Element.props, Decl(renderer2.d.ts, 6, 33)) children?: Element[]; >children : Symbol(children, Decl(renderer2.d.ts, 7, 20)) @@ -137,7 +137,7 @@ export class MyClass implements predom.JSX.Element { >JSX : Symbol(predom.JSX, Decl(renderer2.d.ts, 0, 25)) >Element : Symbol(predom.JSX.Element, Decl(renderer2.d.ts, 4, 9)) - __predomBrand!: void; + __predomBrand!: never; >__predomBrand : Symbol(MyClass.__predomBrand, Decl(component.tsx, 5, 52)) constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {} @@ -260,7 +260,7 @@ class DOMClass implements dom.JSX.Element { >JSX : Symbol(dom.JSX, Decl(renderer.d.ts, 0, 22)) >Element : Symbol(dom.JSX.Element, Decl(renderer.d.ts, 4, 9)) - __domBrand!: void; + __domBrand!: never; >__domBrand : Symbol(DOMClass.__domBrand, Decl(index.tsx, 8, 43)) constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {} diff --git a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.types b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.types index 38bcc1898ebcf..fc2ae69cfcafe 100644 --- a/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.types +++ b/tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.types @@ -6,8 +6,8 @@ export namespace dom { >e : string } interface Element { - __domBrand: void; ->__domBrand : void + __domBrand: never; +>__domBrand : never props: { >props : { children?: Element[]; } @@ -41,8 +41,8 @@ export namespace predom { >e : string } interface Element { - __predomBrand: void; ->__predomBrand : void + __predomBrand: never; +>__predomBrand : never props: { >props : { children?: Element[]; } @@ -110,8 +110,8 @@ export class MyClass implements predom.JSX.Element { >predom : () => predom.JSX.Element >JSX : any - __predomBrand!: void; ->__predomBrand : void + __predomBrand!: never; +>__predomBrand : never constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {} >props : { x: number; y: number; children?: predom.JSX.Element[]; } @@ -246,8 +246,8 @@ class DOMClass implements dom.JSX.Element { >dom : () => dom.JSX.Element >JSX : any - __domBrand!: void; ->__domBrand : void + __domBrand!: never; +>__domBrand : never constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {} >props : { x: number; y: number; children?: dom.JSX.Element[]; } diff --git a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.errors.txt b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.errors.txt index c8490e7e33f7e..f6cb8b1ac5248 100644 --- a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.errors.txt +++ b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.errors.txt @@ -8,7 +8,7 @@ tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__pre [e: string]: {}; } interface Element { - __domBrand: void; + __domBrand: never; children: Element[]; props: {}; } @@ -24,7 +24,7 @@ tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__pre [e: string]: {}; } interface Element { - __predomBrand: void; + __predomBrand: never; children: Element[]; props: {}; } diff --git a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.js b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.js index 4f5123ed67ddf..cd5f1a4ffe869 100644 --- a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.js +++ b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.js @@ -7,7 +7,7 @@ declare global { [e: string]: {}; } interface Element { - __domBrand: void; + __domBrand: never; children: Element[]; props: {}; } @@ -23,7 +23,7 @@ export namespace predom { [e: string]: {}; } interface Element { - __predomBrand: void; + __predomBrand: never; children: Element[]; props: {}; } diff --git a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.symbols b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.symbols index 9e246795292fd..f558457a1191f 100644 --- a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.symbols +++ b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.symbols @@ -14,11 +14,11 @@ declare global { interface Element { >Element : Symbol(Element, Decl(renderer.d.ts, 4, 9)) - __domBrand: void; + __domBrand: never; >__domBrand : Symbol(Element.__domBrand, Decl(renderer.d.ts, 5, 27)) children: Element[]; ->children : Symbol(Element.children, Decl(renderer.d.ts, 6, 29)) +>children : Symbol(Element.children, Decl(renderer.d.ts, 6, 30)) >Element : Symbol(Element, Decl(renderer.d.ts, 4, 9)) props: {}; @@ -54,11 +54,11 @@ export namespace predom { interface Element { >Element : Symbol(Element, Decl(renderer2.d.ts, 4, 9)) - __predomBrand: void; + __predomBrand: never; >__predomBrand : Symbol(Element.__predomBrand, Decl(renderer2.d.ts, 5, 27)) children: Element[]; ->children : Symbol(Element.children, Decl(renderer2.d.ts, 6, 32)) +>children : Symbol(Element.children, Decl(renderer2.d.ts, 6, 33)) >Element : Symbol(Element, Decl(renderer2.d.ts, 4, 9)) props: {}; diff --git a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.types b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.types index 8cb9cf66e7792..ae24b715a457d 100644 --- a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.types +++ b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.types @@ -8,8 +8,8 @@ declare global { >e : string } interface Element { - __domBrand: void; ->__domBrand : void + __domBrand: never; +>__domBrand : never children: Element[]; >children : Element[] @@ -36,8 +36,8 @@ export namespace predom { >e : string } interface Element { - __predomBrand: void; ->__predomBrand : void + __predomBrand: never; +>__predomBrand : never children: Element[]; >children : Element[] diff --git a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt index 6f474663dcb5d..009791dc0f647 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt +++ b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt @@ -264,9 +264,9 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(155,5): error TS2322: Type '(c i4 = i2; // Ok i4 = i3; // Ok - interface Animal { animal: void } - interface Dog extends Animal { dog: void } - interface Cat extends Animal { cat: void } + interface Animal { animal: never } + interface Dog extends Animal { dog: never } + interface Cat extends Animal { cat: never } interface Comparer1 { compare(a: T, b: T): number; diff --git a/tests/baselines/reference/strictFunctionTypesErrors.js b/tests/baselines/reference/strictFunctionTypesErrors.js index d0608f6c1acbc..a927644fa97b3 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.js +++ b/tests/baselines/reference/strictFunctionTypesErrors.js @@ -88,9 +88,9 @@ i4 = i1; // Ok i4 = i2; // Ok i4 = i3; // Ok -interface Animal { animal: void } -interface Dog extends Animal { dog: void } -interface Cat extends Animal { cat: void } +interface Animal { animal: never } +interface Dog extends Animal { dog: never } +interface Cat extends Animal { cat: never } interface Comparer1 { compare(a: T, b: T): number; diff --git a/tests/baselines/reference/strictFunctionTypesErrors.symbols b/tests/baselines/reference/strictFunctionTypesErrors.symbols index f887f15aeaceb..c15586630c1df 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.symbols +++ b/tests/baselines/reference/strictFunctionTypesErrors.symbols @@ -290,22 +290,22 @@ i4 = i3; // Ok >i4 : Symbol(i4, Decl(strictFunctionTypesErrors.ts, 71, 11)) >i3 : Symbol(i3, Decl(strictFunctionTypesErrors.ts, 70, 11)) -interface Animal { animal: void } +interface Animal { animal: never } >Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) >animal : Symbol(Animal.animal, Decl(strictFunctionTypesErrors.ts, 89, 18)) -interface Dog extends Animal { dog: void } ->Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +interface Dog extends Animal { dog: never } +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 34)) >Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) >dog : Symbol(Dog.dog, Decl(strictFunctionTypesErrors.ts, 90, 30)) -interface Cat extends Animal { cat: void } ->Cat : Symbol(Cat, Decl(strictFunctionTypesErrors.ts, 90, 42)) +interface Cat extends Animal { cat: never } +>Cat : Symbol(Cat, Decl(strictFunctionTypesErrors.ts, 90, 43)) >Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) >cat : Symbol(Cat.cat, Decl(strictFunctionTypesErrors.ts, 91, 30)) interface Comparer1 { ->Comparer1 : Symbol(Comparer1, Decl(strictFunctionTypesErrors.ts, 91, 42)) +>Comparer1 : Symbol(Comparer1, Decl(strictFunctionTypesErrors.ts, 91, 43)) >T : Symbol(T, Decl(strictFunctionTypesErrors.ts, 93, 20)) compare(a: T, b: T): number; @@ -318,13 +318,13 @@ interface Comparer1 { declare let animalComparer1: Comparer1; >animalComparer1 : Symbol(animalComparer1, Decl(strictFunctionTypesErrors.ts, 97, 11)) ->Comparer1 : Symbol(Comparer1, Decl(strictFunctionTypesErrors.ts, 91, 42)) +>Comparer1 : Symbol(Comparer1, Decl(strictFunctionTypesErrors.ts, 91, 43)) >Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) declare let dogComparer1: Comparer1; >dogComparer1 : Symbol(dogComparer1, Decl(strictFunctionTypesErrors.ts, 98, 11)) ->Comparer1 : Symbol(Comparer1, Decl(strictFunctionTypesErrors.ts, 91, 42)) ->Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +>Comparer1 : Symbol(Comparer1, Decl(strictFunctionTypesErrors.ts, 91, 43)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 34)) animalComparer1 = dogComparer1; // Ok >animalComparer1 : Symbol(animalComparer1, Decl(strictFunctionTypesErrors.ts, 97, 11)) @@ -354,7 +354,7 @@ declare let animalComparer2: Comparer2; declare let dogComparer2: Comparer2; >dogComparer2 : Symbol(dogComparer2, Decl(strictFunctionTypesErrors.ts, 108, 11)) >Comparer2 : Symbol(Comparer2, Decl(strictFunctionTypesErrors.ts, 101, 31)) ->Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 34)) animalComparer2 = dogComparer2; // Error >animalComparer2 : Symbol(animalComparer2, Decl(strictFunctionTypesErrors.ts, 107, 11)) @@ -388,7 +388,7 @@ declare let animalCrate: Crate; declare let dogCrate: Crate; >dogCrate : Symbol(dogCrate, Decl(strictFunctionTypesErrors.ts, 121, 11)) >Crate : Symbol(Crate, Decl(strictFunctionTypesErrors.ts, 111, 31)) ->Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 34)) // Errors below should elaborate the reason for invariance @@ -413,8 +413,8 @@ declare let fc2: (f: (x: Dog) => Dog) => void; >fc2 : Symbol(fc2, Decl(strictFunctionTypesErrors.ts, 131, 11)) >f : Symbol(f, Decl(strictFunctionTypesErrors.ts, 131, 18)) >x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 131, 22)) ->Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) ->Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 34)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 34)) fc1 = fc2; // Error >fc1 : Symbol(fc1, Decl(strictFunctionTypesErrors.ts, 130, 11)) @@ -442,7 +442,7 @@ namespace n1 { static f2(x: Dog): Animal { throw "wat"; }; >f2 : Symbol(Foo.f2, Decl(strictFunctionTypesErrors.ts, 140, 53)) >x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 141, 18)) ->Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 34)) >Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) } declare let f1: (cb: typeof Foo.f1) => void; @@ -491,7 +491,7 @@ namespace n2 { >f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 152, 15)) >cb : Symbol(cb, Decl(strictFunctionTypesErrors.ts, 152, 21)) >BivariantHack : Symbol(BivariantHack, Decl(strictFunctionTypesErrors.ts, 149, 14)) ->Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 34)) >Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) f1 = f2; diff --git a/tests/baselines/reference/strictFunctionTypesErrors.types b/tests/baselines/reference/strictFunctionTypesErrors.types index cdffc5f49587b..94f01eeeab262 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.types +++ b/tests/baselines/reference/strictFunctionTypesErrors.types @@ -298,14 +298,14 @@ i4 = i3; // Ok >i4 : Func> >i3 : Func> -interface Animal { animal: void } ->animal : void +interface Animal { animal: never } +>animal : never -interface Dog extends Animal { dog: void } ->dog : void +interface Dog extends Animal { dog: never } +>dog : never -interface Cat extends Animal { cat: void } ->cat : void +interface Cat extends Animal { cat: never } +>cat : never interface Comparer1 { compare(a: T, b: T): number; diff --git a/tests/baselines/reference/typesWithVoidProperty.errors.txt b/tests/baselines/reference/typesWithVoidProperty.errors.txt new file mode 100644 index 0000000000000..9a99aeec130ed --- /dev/null +++ b/tests/baselines/reference/typesWithVoidProperty.errors.txt @@ -0,0 +1,136 @@ +tests/cases/conformance/types/members/typesWithVoidProperty.ts(16,1): error TS2322: Type 'X' is not assignable to type 'X'. + Type 'void' is not assignable to type 'number'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(17,1): error TS2322: Type 'X' is not assignable to type 'X'. + Type 'number | void' is not assignable to type 'number'. + Type 'void' is not assignable to type 'number'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(18,1): error TS2322: Type 'Y' is not assignable to type 'X'. + Types of property 'value' are incompatible. + Type 'number | undefined' is not assignable to type 'number'. + Type 'undefined' is not assignable to type 'number'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(19,1): error TS2741: Property 'value' is missing in type '{ done: true; }' but required in type 'X'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(21,19): error TS2322: Type 'undefined' is not assignable to type 'number'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(22,19): error TS2322: Type 'undefined' is not assignable to type 'number'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(23,19): error TS2322: Type 'void' is not assignable to type 'number'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(25,1): error TS2322: Type 'X' is not assignable to type 'X'. + Type 'number' is not assignable to type 'void'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(26,1): error TS2322: Type 'X' is not assignable to type 'X'. + Type 'number | void' is not assignable to type 'void'. + Type 'number' is not assignable to type 'void'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(27,1): error TS2322: Type 'Y' is not assignable to type 'X'. + Types of property 'value' are incompatible. + Type 'number | undefined' is not assignable to type 'void'. + Type 'number' is not assignable to type 'void'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(29,19): error TS2322: Type 'number' is not assignable to type 'void'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(44,1): error TS2322: Type 'X' is not assignable to type 'Y'. + Types of property 'value' are incompatible. + Type 'void' is not assignable to type 'number | undefined'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(45,1): error TS2322: Type 'X' is not assignable to type 'Y'. + Types of property 'value' are incompatible. + Type 'number | void' is not assignable to type 'number | undefined'. + Type 'void' is not assignable to type 'number | undefined'. +tests/cases/conformance/types/members/typesWithVoidProperty.ts(50,19): error TS2322: Type 'void' is not assignable to type 'number | undefined'. + + +==== tests/cases/conformance/types/members/typesWithVoidProperty.ts (14 errors) ==== + interface X { + done: true; + value: T; + } + + interface Y { + done: true; + value?: T; + } + + declare let a: X; + declare let b: X; + declare let c: X; + declare let d: Y; + + a = b; // not allowed because `value` must be `number` + ~ +!!! error TS2322: Type 'X' is not assignable to type 'X'. +!!! error TS2322: Type 'void' is not assignable to type 'number'. + a = c; // not allowed because `value` must be `number` + ~ +!!! error TS2322: Type 'X' is not assignable to type 'X'. +!!! error TS2322: Type 'number | void' is not assignable to type 'number'. +!!! error TS2322: Type 'void' is not assignable to type 'number'. + a = d; // not allowed because `value` must be `number` + ~ +!!! error TS2322: Type 'Y' is not assignable to type 'X'. +!!! error TS2322: Types of property 'value' are incompatible. +!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'. +!!! error TS2322: Type 'undefined' is not assignable to type 'number'. + a = { done: true }; // not allowed because `value` is not optional (non-`void`) + ~ +!!! error TS2741: Property 'value' is missing in type '{ done: true; }' but required in type 'X'. +!!! related TS2728 tests/cases/conformance/types/members/typesWithVoidProperty.ts:3:5: 'value' is declared here. + a = { done: true, value: 1 }; // allowed because `value` must be `number` + a = { done: true, value: undefined }; // not allowed because `value` must be `number` + ~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'number'. +!!! related TS6500 tests/cases/conformance/types/members/typesWithVoidProperty.ts:3:5: The expected type comes from property 'value' which is declared here on type 'X' + a = { done: true, value: undefined as undefined }; // not allowed because `value` must be `number` + ~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'number'. +!!! related TS6500 tests/cases/conformance/types/members/typesWithVoidProperty.ts:3:5: The expected type comes from property 'value' which is declared here on type 'X' + a = { done: true, value: undefined as void }; // not allowed because `value` must be `number` + ~~~~~ +!!! error TS2322: Type 'void' is not assignable to type 'number'. +!!! related TS6500 tests/cases/conformance/types/members/typesWithVoidProperty.ts:3:5: The expected type comes from property 'value' which is declared here on type 'X' + + b = a; // not allowed because `value` must be `void` + ~ +!!! error TS2322: Type 'X' is not assignable to type 'X'. +!!! error TS2322: Type 'number' is not assignable to type 'void'. + b = c; // not allowed because `value` must be `void` + ~ +!!! error TS2322: Type 'X' is not assignable to type 'X'. +!!! error TS2322: Type 'number | void' is not assignable to type 'void'. +!!! error TS2322: Type 'number' is not assignable to type 'void'. + b = d; // not allowed because `value` must be `void` + ~ +!!! error TS2322: Type 'Y' is not assignable to type 'X'. +!!! error TS2322: Types of property 'value' are incompatible. +!!! error TS2322: Type 'number | undefined' is not assignable to type 'void'. +!!! error TS2322: Type 'number' is not assignable to type 'void'. + b = { done: true }; // allowed because `value` is optional due to `void` + b = { done: true, value: 1 }; // not allowed because `value` must be `void` + ~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'void'. +!!! related TS6500 tests/cases/conformance/types/members/typesWithVoidProperty.ts:3:5: The expected type comes from property 'value' which is declared here on type 'X' + b = { done: true, value: undefined }; // allowed because `value` can be `undefined` (assignable to `void`) + b = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` (assignable to `void`) + b = { done: true, value: undefined as void }; // allowed because `value` must be `void` + + c = a; // allowed because `value` can be `number` + c = b; // allowed because `value` can be `void` + c = d; // allowed because `value` can be `undefined` + c = { done: true }; // allowed because `value` is optional due to `void` + c = { done: true, value: 1 }; // allowed because `value` can be `number` + c = { done: true, value: undefined }; // allowed because `value` can be `undefined` (assignable to `void`) + c = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` (assignable to `void`) + c = { done: true, value: undefined as void }; // allowed because `value` can be `void` + + d = a; // allowed because `value` must be `number | void` + d = b; // not allowed because `value` must be `undefined`, and `void` is a supertype of `undefined` + ~ +!!! error TS2322: Type 'X' is not assignable to type 'Y'. +!!! error TS2322: Types of property 'value' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'number | undefined'. + d = c; // not allowed allowed because `value` must be `undefined`, and `void` is a supertype of `undefined` + ~ +!!! error TS2322: Type 'X' is not assignable to type 'Y'. +!!! error TS2322: Types of property 'value' are incompatible. +!!! error TS2322: Type 'number | void' is not assignable to type 'number | undefined'. +!!! error TS2322: Type 'void' is not assignable to type 'number | undefined'. + d = { done: true }; // allowed because `value` is optional + d = { done: true, value: 1 }; // allowed because `value` can be `number` + d = { done: true, value: undefined }; // allowed because `value` can be `undefined` + d = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` + d = { done: true, value: undefined as void }; // not allowed because `value` can be `undefined`, and `void` is a supertype of `undefined + ~~~~~ +!!! error TS2322: Type 'void' is not assignable to type 'number | undefined'. +!!! related TS6500 tests/cases/conformance/types/members/typesWithVoidProperty.ts:8:5: The expected type comes from property 'value' which is declared here on type 'Y' + \ No newline at end of file diff --git a/tests/baselines/reference/typesWithVoidProperty.symbols b/tests/baselines/reference/typesWithVoidProperty.symbols new file mode 100644 index 0000000000000..feed8a93e2a2b --- /dev/null +++ b/tests/baselines/reference/typesWithVoidProperty.symbols @@ -0,0 +1,197 @@ +=== tests/cases/conformance/types/members/typesWithVoidProperty.ts === +interface X { +>X : Symbol(X, Decl(typesWithVoidProperty.ts, 0, 0)) +>T : Symbol(T, Decl(typesWithVoidProperty.ts, 0, 12)) + + done: true; +>done : Symbol(X.done, Decl(typesWithVoidProperty.ts, 0, 16)) + + value: T; +>value : Symbol(X.value, Decl(typesWithVoidProperty.ts, 1, 15)) +>T : Symbol(T, Decl(typesWithVoidProperty.ts, 0, 12)) +} + +interface Y { +>Y : Symbol(Y, Decl(typesWithVoidProperty.ts, 3, 1)) +>T : Symbol(T, Decl(typesWithVoidProperty.ts, 5, 12)) + + done: true; +>done : Symbol(Y.done, Decl(typesWithVoidProperty.ts, 5, 16)) + + value?: T; +>value : Symbol(Y.value, Decl(typesWithVoidProperty.ts, 6, 15)) +>T : Symbol(T, Decl(typesWithVoidProperty.ts, 5, 12)) +} + +declare let a: X; +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) +>X : Symbol(X, Decl(typesWithVoidProperty.ts, 0, 0)) + +declare let b: X; +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) +>X : Symbol(X, Decl(typesWithVoidProperty.ts, 0, 0)) + +declare let c: X; +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) +>X : Symbol(X, Decl(typesWithVoidProperty.ts, 0, 0)) + +declare let d: Y; +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) +>Y : Symbol(Y, Decl(typesWithVoidProperty.ts, 3, 1)) + +a = b; // not allowed because `value` must be `number` +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) + +a = c; // not allowed because `value` must be `number` +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) + +a = d; // not allowed because `value` must be `number` +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) + +a = { done: true }; // not allowed because `value` is not optional (non-`void`) +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 18, 5)) + +a = { done: true, value: 1 }; // allowed because `value` must be `number` +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 19, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 19, 17)) + +a = { done: true, value: undefined }; // not allowed because `value` must be `number` +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 20, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 20, 17)) +>undefined : Symbol(undefined) + +a = { done: true, value: undefined as undefined }; // not allowed because `value` must be `number` +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 21, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 21, 17)) +>undefined : Symbol(undefined) + +a = { done: true, value: undefined as void }; // not allowed because `value` must be `number` +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 22, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 22, 17)) +>undefined : Symbol(undefined) + +b = a; // not allowed because `value` must be `void` +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) + +b = c; // not allowed because `value` must be `void` +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) + +b = d; // not allowed because `value` must be `void` +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) + +b = { done: true }; // allowed because `value` is optional due to `void` +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 27, 5)) + +b = { done: true, value: 1 }; // not allowed because `value` must be `void` +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 28, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 28, 17)) + +b = { done: true, value: undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 29, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 29, 17)) +>undefined : Symbol(undefined) + +b = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 30, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 30, 17)) +>undefined : Symbol(undefined) + +b = { done: true, value: undefined as void }; // allowed because `value` must be `void` +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 31, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 31, 17)) +>undefined : Symbol(undefined) + +c = a; // allowed because `value` can be `number` +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) + +c = b; // allowed because `value` can be `void` +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) + +c = d; // allowed because `value` can be `undefined` +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) + +c = { done: true }; // allowed because `value` is optional due to `void` +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 36, 5)) + +c = { done: true, value: 1 }; // allowed because `value` can be `number` +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 37, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 37, 17)) + +c = { done: true, value: undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 38, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 38, 17)) +>undefined : Symbol(undefined) + +c = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 39, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 39, 17)) +>undefined : Symbol(undefined) + +c = { done: true, value: undefined as void }; // allowed because `value` can be `void` +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 40, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 40, 17)) +>undefined : Symbol(undefined) + +d = a; // allowed because `value` must be `number | void` +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) +>a : Symbol(a, Decl(typesWithVoidProperty.ts, 10, 11)) + +d = b; // not allowed because `value` must be `undefined`, and `void` is a supertype of `undefined` +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) +>b : Symbol(b, Decl(typesWithVoidProperty.ts, 11, 11)) + +d = c; // not allowed allowed because `value` must be `undefined`, and `void` is a supertype of `undefined` +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) +>c : Symbol(c, Decl(typesWithVoidProperty.ts, 12, 11)) + +d = { done: true }; // allowed because `value` is optional +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 45, 5)) + +d = { done: true, value: 1 }; // allowed because `value` can be `number` +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 46, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 46, 17)) + +d = { done: true, value: undefined }; // allowed because `value` can be `undefined` +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 47, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 47, 17)) +>undefined : Symbol(undefined) + +d = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 48, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 48, 17)) +>undefined : Symbol(undefined) + +d = { done: true, value: undefined as void }; // not allowed because `value` can be `undefined`, and `void` is a supertype of `undefined +>d : Symbol(d, Decl(typesWithVoidProperty.ts, 13, 11)) +>done : Symbol(done, Decl(typesWithVoidProperty.ts, 49, 5)) +>value : Symbol(value, Decl(typesWithVoidProperty.ts, 49, 17)) +>undefined : Symbol(undefined) + diff --git a/tests/baselines/reference/typesWithVoidProperty.types b/tests/baselines/reference/typesWithVoidProperty.types new file mode 100644 index 0000000000000..7669dc40b8928 --- /dev/null +++ b/tests/baselines/reference/typesWithVoidProperty.types @@ -0,0 +1,271 @@ +=== tests/cases/conformance/types/members/typesWithVoidProperty.ts === +interface X { + done: true; +>done : true +>true : true + + value: T; +>value : T +} + +interface Y { + done: true; +>done : true +>true : true + + value?: T; +>value : T | undefined +} + +declare let a: X; +>a : X + +declare let b: X; +>b : X + +declare let c: X; +>c : X + +declare let d: Y; +>d : Y + +a = b; // not allowed because `value` must be `number` +>a = b : X +>a : X +>b : X + +a = c; // not allowed because `value` must be `number` +>a = c : X +>a : X +>c : X + +a = d; // not allowed because `value` must be `number` +>a = d : Y +>a : X +>d : Y + +a = { done: true }; // not allowed because `value` is not optional (non-`void`) +>a = { done: true } : { done: true; } +>a : X +>{ done: true } : { done: true; } +>done : true +>true : true + +a = { done: true, value: 1 }; // allowed because `value` must be `number` +>a = { done: true, value: 1 } : { done: true; value: number; } +>a : X +>{ done: true, value: 1 } : { done: true; value: number; } +>done : true +>true : true +>value : number +>1 : 1 + +a = { done: true, value: undefined }; // not allowed because `value` must be `number` +>a = { done: true, value: undefined } : { done: true; value: undefined; } +>a : X +>{ done: true, value: undefined } : { done: true; value: undefined; } +>done : true +>true : true +>value : undefined +>undefined : undefined + +a = { done: true, value: undefined as undefined }; // not allowed because `value` must be `number` +>a = { done: true, value: undefined as undefined } : { done: true; value: undefined; } +>a : X +>{ done: true, value: undefined as undefined } : { done: true; value: undefined; } +>done : true +>true : true +>value : undefined +>undefined as undefined : undefined +>undefined : undefined + +a = { done: true, value: undefined as void }; // not allowed because `value` must be `number` +>a = { done: true, value: undefined as void } : { done: true; value: void; } +>a : X +>{ done: true, value: undefined as void } : { done: true; value: void; } +>done : true +>true : true +>value : void +>undefined as void : void +>undefined : undefined + +b = a; // not allowed because `value` must be `void` +>b = a : X +>b : X +>a : X + +b = c; // not allowed because `value` must be `void` +>b = c : X +>b : X +>c : X + +b = d; // not allowed because `value` must be `void` +>b = d : Y +>b : X +>d : Y + +b = { done: true }; // allowed because `value` is optional due to `void` +>b = { done: true } : { done: true; } +>b : X +>{ done: true } : { done: true; } +>done : true +>true : true + +b = { done: true, value: 1 }; // not allowed because `value` must be `void` +>b = { done: true, value: 1 } : { done: true; value: number; } +>b : X +>{ done: true, value: 1 } : { done: true; value: number; } +>done : true +>true : true +>value : number +>1 : 1 + +b = { done: true, value: undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +>b = { done: true, value: undefined } : { done: true; value: undefined; } +>b : X +>{ done: true, value: undefined } : { done: true; value: undefined; } +>done : true +>true : true +>value : undefined +>undefined : undefined + +b = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +>b = { done: true, value: undefined as undefined } : { done: true; value: undefined; } +>b : X +>{ done: true, value: undefined as undefined } : { done: true; value: undefined; } +>done : true +>true : true +>value : undefined +>undefined as undefined : undefined +>undefined : undefined + +b = { done: true, value: undefined as void }; // allowed because `value` must be `void` +>b = { done: true, value: undefined as void } : { done: true; value: void; } +>b : X +>{ done: true, value: undefined as void } : { done: true; value: void; } +>done : true +>true : true +>value : void +>undefined as void : void +>undefined : undefined + +c = a; // allowed because `value` can be `number` +>c = a : X +>c : X +>a : X + +c = b; // allowed because `value` can be `void` +>c = b : X +>c : X +>b : X + +c = d; // allowed because `value` can be `undefined` +>c = d : Y +>c : X +>d : Y + +c = { done: true }; // allowed because `value` is optional due to `void` +>c = { done: true } : { done: true; } +>c : X +>{ done: true } : { done: true; } +>done : true +>true : true + +c = { done: true, value: 1 }; // allowed because `value` can be `number` +>c = { done: true, value: 1 } : { done: true; value: number; } +>c : X +>{ done: true, value: 1 } : { done: true; value: number; } +>done : true +>true : true +>value : number +>1 : 1 + +c = { done: true, value: undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +>c = { done: true, value: undefined } : { done: true; value: undefined; } +>c : X +>{ done: true, value: undefined } : { done: true; value: undefined; } +>done : true +>true : true +>value : undefined +>undefined : undefined + +c = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +>c = { done: true, value: undefined as undefined } : { done: true; value: undefined; } +>c : X +>{ done: true, value: undefined as undefined } : { done: true; value: undefined; } +>done : true +>true : true +>value : undefined +>undefined as undefined : undefined +>undefined : undefined + +c = { done: true, value: undefined as void }; // allowed because `value` can be `void` +>c = { done: true, value: undefined as void } : { done: true; value: void; } +>c : X +>{ done: true, value: undefined as void } : { done: true; value: void; } +>done : true +>true : true +>value : void +>undefined as void : void +>undefined : undefined + +d = a; // allowed because `value` must be `number | void` +>d = a : X +>d : Y +>a : X + +d = b; // not allowed because `value` must be `undefined`, and `void` is a supertype of `undefined` +>d = b : X +>d : Y +>b : X + +d = c; // not allowed allowed because `value` must be `undefined`, and `void` is a supertype of `undefined` +>d = c : X +>d : Y +>c : X + +d = { done: true }; // allowed because `value` is optional +>d = { done: true } : { done: true; } +>d : Y +>{ done: true } : { done: true; } +>done : true +>true : true + +d = { done: true, value: 1 }; // allowed because `value` can be `number` +>d = { done: true, value: 1 } : { done: true; value: number; } +>d : Y +>{ done: true, value: 1 } : { done: true; value: number; } +>done : true +>true : true +>value : number +>1 : 1 + +d = { done: true, value: undefined }; // allowed because `value` can be `undefined` +>d = { done: true, value: undefined } : { done: true; value: undefined; } +>d : Y +>{ done: true, value: undefined } : { done: true; value: undefined; } +>done : true +>true : true +>value : undefined +>undefined : undefined + +d = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` +>d = { done: true, value: undefined as undefined } : { done: true; value: undefined; } +>d : Y +>{ done: true, value: undefined as undefined } : { done: true; value: undefined; } +>done : true +>true : true +>value : undefined +>undefined as undefined : undefined +>undefined : undefined + +d = { done: true, value: undefined as void }; // not allowed because `value` can be `undefined`, and `void` is a supertype of `undefined +>d = { done: true, value: undefined as void } : { done: true; value: void; } +>d : Y +>{ done: true, value: undefined as void } : { done: true; value: void; } +>done : true +>true : true +>value : void +>undefined as void : void +>undefined : undefined + diff --git a/tests/cases/compiler/strictFunctionTypesErrors.ts b/tests/cases/compiler/strictFunctionTypesErrors.ts index 3f86f2529c08e..bf21a236571c8 100644 --- a/tests/cases/compiler/strictFunctionTypesErrors.ts +++ b/tests/cases/compiler/strictFunctionTypesErrors.ts @@ -88,9 +88,9 @@ i4 = i1; // Ok i4 = i2; // Ok i4 = i3; // Ok -interface Animal { animal: void } -interface Dog extends Animal { dog: void } -interface Cat extends Animal { cat: void } +interface Animal { animal: never } +interface Dog extends Animal { dog: never } +interface Cat extends Animal { cat: never } interface Comparer1 { compare(a: T, b: T): number; diff --git a/tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarationsLocalTypes.tsx b/tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarationsLocalTypes.tsx index 009abe2e852c8..45e8a6314440d 100644 --- a/tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarationsLocalTypes.tsx +++ b/tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarationsLocalTypes.tsx @@ -6,7 +6,7 @@ export namespace dom { [e: string]: {}; } interface Element { - __domBrand: void; + __domBrand: never; props: { children?: Element[]; }; @@ -26,7 +26,7 @@ export namespace predom { [e: string]: {}; } interface Element { - __predomBrand: void; + __predomBrand: never; props: { children?: Element[]; }; @@ -46,7 +46,7 @@ import { predom } from "./renderer2" export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) =>

{props.x} + {props.y} = {props.x + props.y}{...this.props.children}

; export class MyClass implements predom.JSX.Element { - __predomBrand!: void; + __predomBrand!: never; constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {} render() { return

@@ -69,7 +69,7 @@ elem = ; // Expect assignability error here const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) =>

{props.x} + {props.y} = {props.x + props.y}{props.children}

; class DOMClass implements dom.JSX.Element { - __domBrand!: void; + __domBrand!: never; constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {} render() { return

{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}

; diff --git a/tests/cases/conformance/jsx/inline/inlineJsxFactoryLocalTypeGlobalFallback.tsx b/tests/cases/conformance/jsx/inline/inlineJsxFactoryLocalTypeGlobalFallback.tsx index 3f4340f518b4b..1f2974d7062a8 100644 --- a/tests/cases/conformance/jsx/inline/inlineJsxFactoryLocalTypeGlobalFallback.tsx +++ b/tests/cases/conformance/jsx/inline/inlineJsxFactoryLocalTypeGlobalFallback.tsx @@ -6,7 +6,7 @@ declare global { [e: string]: {}; } interface Element { - __domBrand: void; + __domBrand: never; children: Element[]; props: {}; } @@ -22,7 +22,7 @@ export namespace predom { [e: string]: {}; } interface Element { - __predomBrand: void; + __predomBrand: never; children: Element[]; props: {}; } diff --git a/tests/cases/conformance/types/members/typesWithVoidProperty.ts b/tests/cases/conformance/types/members/typesWithVoidProperty.ts new file mode 100644 index 0000000000000..ce04049309fd9 --- /dev/null +++ b/tests/cases/conformance/types/members/typesWithVoidProperty.ts @@ -0,0 +1,53 @@ +// @strict: true +// @noEmit: true + +interface X { + done: true; + value: T; +} + +interface Y { + done: true; + value?: T; +} + +declare let a: X; +declare let b: X; +declare let c: X; +declare let d: Y; + +a = b; // not allowed because `value` must be `number` +a = c; // not allowed because `value` must be `number` +a = d; // not allowed because `value` must be `number` +a = { done: true }; // not allowed because `value` is not optional (non-`void`) +a = { done: true, value: 1 }; // allowed because `value` must be `number` +a = { done: true, value: undefined }; // not allowed because `value` must be `number` +a = { done: true, value: undefined as undefined }; // not allowed because `value` must be `number` +a = { done: true, value: undefined as void }; // not allowed because `value` must be `number` + +b = a; // not allowed because `value` must be `void` +b = c; // not allowed because `value` must be `void` +b = d; // not allowed because `value` must be `void` +b = { done: true }; // allowed because `value` is optional due to `void` +b = { done: true, value: 1 }; // not allowed because `value` must be `void` +b = { done: true, value: undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +b = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +b = { done: true, value: undefined as void }; // allowed because `value` must be `void` + +c = a; // allowed because `value` can be `number` +c = b; // allowed because `value` can be `void` +c = d; // allowed because `value` can be `undefined` +c = { done: true }; // allowed because `value` is optional due to `void` +c = { done: true, value: 1 }; // allowed because `value` can be `number` +c = { done: true, value: undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +c = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` (assignable to `void`) +c = { done: true, value: undefined as void }; // allowed because `value` can be `void` + +d = a; // allowed because `value` must be `number | void` +d = b; // not allowed because `value` must be `undefined`, and `void` is a supertype of `undefined` +d = c; // not allowed allowed because `value` must be `undefined`, and `void` is a supertype of `undefined` +d = { done: true }; // allowed because `value` is optional +d = { done: true, value: 1 }; // allowed because `value` can be `number` +d = { done: true, value: undefined }; // allowed because `value` can be `undefined` +d = { done: true, value: undefined as undefined }; // allowed because `value` can be `undefined` +d = { done: true, value: undefined as void }; // not allowed because `value` can be `undefined`, and `void` is a supertype of `undefined