diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 80853ca2eaf3e..247c789577c1a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12822,12 +12822,22 @@ namespace ts { } return Ternary.False; + function isNonGeneric(type: Type) { + // If we're already in identity relationship checking, we should use `isRelatedTo` + // to catch the `Maybe` from an excessively deep type (which we then assume means + // that the type could possibly contain a generic) + if (relation === identityRelation) { + return isRelatedTo(type, getPermissiveInstantiation(type)) === Ternary.True; + } + return isTypeIdenticalTo(type, getPermissiveInstantiation(type)); + } + function relateVariances(sourceTypeArguments: ReadonlyArray | undefined, targetTypeArguments: ReadonlyArray | undefined, variances: Variance[]) { if (result = typeArgumentsRelatedTo(sourceTypeArguments, targetTypeArguments, variances, reportErrors)) { return result; } - const isCovariantVoid = targetTypeArguments && hasCovariantVoidArgument(targetTypeArguments, variances); - varianceCheckFailed = !isCovariantVoid; + const allowStructuralFallback = (targetTypeArguments && hasCovariantVoidArgument(targetTypeArguments, variances)) || isNonGeneric(source) || isNonGeneric(target); + varianceCheckFailed = !allowStructuralFallback; // The type arguments did not relate appropriately, but it may be because we have no variance // information (in which case typeArgumentsRelatedTo defaulted to covariance for all type // arguments). It might also be the case that the target type has a 'void' type argument for @@ -12835,7 +12845,7 @@ namespace ts { // (in which case any type argument is permitted on the source side). In those cases we proceed // with a structural comparison. Otherwise, we know for certain the instantiations aren't // related and we can return here. - if (variances !== emptyArray && !isCovariantVoid) { + if (variances !== emptyArray && !allowStructuralFallback) { // In some cases generic types that are covariant in regular type checking mode become // invariant in --strictFunctionTypes mode because one or more type parameters are used in // both co- and contravariant positions. In order to make it easier to diagnose *why* such diff --git a/tests/baselines/reference/checkInfiniteExpansionTermination.errors.txt b/tests/baselines/reference/checkInfiniteExpansionTermination.errors.txt deleted file mode 100644 index 014087ff6275e..0000000000000 --- a/tests/baselines/reference/checkInfiniteExpansionTermination.errors.txt +++ /dev/null @@ -1,32 +0,0 @@ -tests/cases/compiler/checkInfiniteExpansionTermination.ts(16,1): error TS2322: Type 'ISubject' is not assignable to type 'IObservable'. - Types of property 'n' are incompatible. - Type 'IObservable' is not assignable to type 'IObservable'. - Type 'Bar[]' is not assignable to type 'Foo[]'. - Property 'x' is missing in type 'Bar' but required in type 'Foo'. - - -==== tests/cases/compiler/checkInfiniteExpansionTermination.ts (1 errors) ==== - // Regression test for #1002 - // Before fix this code would cause infinite loop - - interface IObservable { - n: IObservable; // Needed, must be T[] - } - - // Needed - interface ISubject extends IObservable { } - - interface Foo { x } - interface Bar { y } - - var values: IObservable; - var values2: ISubject; - values = values2; - ~~~~~~ -!!! error TS2322: Type 'ISubject' is not assignable to type 'IObservable'. -!!! error TS2322: Types of property 'n' are incompatible. -!!! error TS2322: Type 'IObservable' is not assignable to type 'IObservable'. -!!! error TS2322: Type 'Bar[]' is not assignable to type 'Foo[]'. -!!! error TS2322: Property 'x' is missing in type 'Bar' but required in type 'Foo'. -!!! related TS2728 tests/cases/compiler/checkInfiniteExpansionTermination.ts:11:17: 'x' is declared here. - \ No newline at end of file diff --git a/tests/baselines/reference/invariantGenericErrorElaboration.errors.txt b/tests/baselines/reference/invariantGenericErrorElaboration.errors.txt deleted file mode 100644 index 0bd79bcf11d6a..0000000000000 --- a/tests/baselines/reference/invariantGenericErrorElaboration.errors.txt +++ /dev/null @@ -1,52 +0,0 @@ -tests/cases/compiler/invariantGenericErrorElaboration.ts(3,7): error TS2322: Type 'Num' is not assignable to type 'Runtype'. - Types of property 'constraint' are incompatible. - Type 'Constraint' is not assignable to type 'Constraint>'. - Types of property 'constraint' are incompatible. - Type 'Constraint>' is not assignable to type 'Constraint>>'. - Types of property 'constraint' are incompatible. - Type 'Constraint>>' is not assignable to type 'Constraint>>>'. - Type 'Constraint>>' is not assignable to type 'Constraint>'. - Types of property 'underlying' are incompatible. - Type 'Constraint>' is not assignable to type 'Constraint'. -tests/cases/compiler/invariantGenericErrorElaboration.ts(4,19): error TS2322: Type 'Num' is not assignable to type 'Runtype'. - - -==== tests/cases/compiler/invariantGenericErrorElaboration.ts (2 errors) ==== - // Repro from #19746 - - const wat: Runtype = Num; - ~~~ -!!! error TS2322: Type 'Num' is not assignable to type 'Runtype'. -!!! error TS2322: Types of property 'constraint' are incompatible. -!!! error TS2322: Type 'Constraint' is not assignable to type 'Constraint>'. -!!! error TS2322: Types of property 'constraint' are incompatible. -!!! error TS2322: Type 'Constraint>' is not assignable to type 'Constraint>>'. -!!! error TS2322: Types of property 'constraint' are incompatible. -!!! error TS2322: Type 'Constraint>>' is not assignable to type 'Constraint>>>'. -!!! error TS2322: Type 'Constraint>>' is not assignable to type 'Constraint>'. -!!! error TS2322: Types of property 'underlying' are incompatible. -!!! error TS2322: Type 'Constraint>' is not assignable to type 'Constraint'. -!!! related TS2728 tests/cases/compiler/invariantGenericErrorElaboration.ts:12:3: 'tag' is declared here. - const Foo = Obj({ foo: Num }) - ~~~ -!!! error TS2322: Type 'Num' is not assignable to type 'Runtype'. -!!! related TS6501 tests/cases/compiler/invariantGenericErrorElaboration.ts:17:34: The expected type comes from this index signature. - - interface Runtype { - constraint: Constraint - witness: A - } - - interface Num extends Runtype { - tag: 'number' - } - declare const Num: Num - - interface Obj }> extends Runtype<{[K in keyof O]: O[K]['witness'] }> {} - declare function Obj }>(fields: O): Obj; - - interface Constraint> extends Runtype { - underlying: A, - check: (x: A['witness']) => void, - } - \ No newline at end of file diff --git a/tests/baselines/reference/invariantGenericErrorElaboration.types b/tests/baselines/reference/invariantGenericErrorElaboration.types index 7c4bdd46d037f..86aec86face81 100644 --- a/tests/baselines/reference/invariantGenericErrorElaboration.types +++ b/tests/baselines/reference/invariantGenericErrorElaboration.types @@ -6,8 +6,8 @@ const wat: Runtype = Num; >Num : Num const Foo = Obj({ foo: Num }) ->Foo : any ->Obj({ foo: Num }) : any +>Foo : Obj<{ foo: Num; }> +>Obj({ foo: Num }) : Obj<{ foo: Num; }> >Obj : ; }>(fields: O) => Obj >{ foo: Num } : { foo: Num; } >foo : Num diff --git a/tests/baselines/reference/mappedTypeRelationships.errors.txt b/tests/baselines/reference/mappedTypeRelationships.errors.txt index 3d63765407972..60a06e000c255 100644 --- a/tests/baselines/reference/mappedTypeRelationships.errors.txt +++ b/tests/baselines/reference/mappedTypeRelationships.errors.txt @@ -34,9 +34,7 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2 tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2542: Index signature in type 'Readonly' only permits reading. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(72,5): error TS2322: Type 'Partial' is not assignable to type 'T'. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(78,5): error TS2322: Type 'Partial' is not assignable to type 'Partial'. - Type 'Thing' is not assignable to type 'T'. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(88,5): error TS2322: Type 'Readonly' is not assignable to type 'Readonly'. - Type 'Thing' is not assignable to type 'T'. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(127,5): error TS2322: Type 'Partial' is not assignable to type 'Identity'. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(143,5): error TS2322: Type '{ [P in keyof T]: T[P]; }' is not assignable to type '{ [P in keyof T]: U[P]; }'. Type 'T[P]' is not assignable to type 'U[P]'. @@ -199,7 +197,6 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS y = x; // Error ~ !!! error TS2322: Type 'Partial' is not assignable to type 'Partial'. -!!! error TS2322: Type 'Thing' is not assignable to type 'T'. } function f40(x: T, y: Readonly) { @@ -212,7 +209,6 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS y = x; // Error ~ !!! error TS2322: Type 'Readonly' is not assignable to type 'Readonly'. -!!! error TS2322: Type 'Thing' is not assignable to type 'T'. } type Item = { diff --git a/tests/baselines/reference/nongenericPartialInstantiationsRelatedInBothDirections.js b/tests/baselines/reference/nongenericPartialInstantiationsRelatedInBothDirections.js new file mode 100644 index 0000000000000..630adb92c4312 --- /dev/null +++ b/tests/baselines/reference/nongenericPartialInstantiationsRelatedInBothDirections.js @@ -0,0 +1,18 @@ +//// [nongenericPartialInstantiationsRelatedInBothDirections.ts] +interface Foo { + a: number; + b: number; + bar: string; +} +interface ObjectContaining { + new (sample: Partial): Partial +} +declare let cafoo: ObjectContaining<{ a: number, foo: number }>; +declare let cfoo: ObjectContaining; +cfoo = cafoo; +cafoo = cfoo; + + +//// [nongenericPartialInstantiationsRelatedInBothDirections.js] +cfoo = cafoo; +cafoo = cfoo; diff --git a/tests/baselines/reference/nongenericPartialInstantiationsRelatedInBothDirections.symbols b/tests/baselines/reference/nongenericPartialInstantiationsRelatedInBothDirections.symbols new file mode 100644 index 0000000000000..ee61fa0fd88d9 --- /dev/null +++ b/tests/baselines/reference/nongenericPartialInstantiationsRelatedInBothDirections.symbols @@ -0,0 +1,43 @@ +=== tests/cases/compiler/nongenericPartialInstantiationsRelatedInBothDirections.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 0, 0)) + + a: number; +>a : Symbol(Foo.a, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 0, 15)) + + b: number; +>b : Symbol(Foo.b, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 1, 14)) + + bar: string; +>bar : Symbol(Foo.bar, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 2, 14)) +} +interface ObjectContaining { +>ObjectContaining : Symbol(ObjectContaining, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 4, 1)) +>T : Symbol(T, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 5, 27)) + + new (sample: Partial): Partial +>sample : Symbol(sample, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 6, 7)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 5, 27)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 5, 27)) +} +declare let cafoo: ObjectContaining<{ a: number, foo: number }>; +>cafoo : Symbol(cafoo, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 8, 11)) +>ObjectContaining : Symbol(ObjectContaining, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 4, 1)) +>a : Symbol(a, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 8, 37)) +>foo : Symbol(foo, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 8, 48)) + +declare let cfoo: ObjectContaining; +>cfoo : Symbol(cfoo, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 9, 11)) +>ObjectContaining : Symbol(ObjectContaining, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 4, 1)) +>Foo : Symbol(Foo, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 0, 0)) + +cfoo = cafoo; +>cfoo : Symbol(cfoo, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 9, 11)) +>cafoo : Symbol(cafoo, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 8, 11)) + +cafoo = cfoo; +>cafoo : Symbol(cafoo, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 8, 11)) +>cfoo : Symbol(cfoo, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 9, 11)) + diff --git a/tests/baselines/reference/nongenericPartialInstantiationsRelatedInBothDirections.types b/tests/baselines/reference/nongenericPartialInstantiationsRelatedInBothDirections.types new file mode 100644 index 0000000000000..cbce9ce867b4d --- /dev/null +++ b/tests/baselines/reference/nongenericPartialInstantiationsRelatedInBothDirections.types @@ -0,0 +1,33 @@ +=== tests/cases/compiler/nongenericPartialInstantiationsRelatedInBothDirections.ts === +interface Foo { + a: number; +>a : number + + b: number; +>b : number + + bar: string; +>bar : string +} +interface ObjectContaining { + new (sample: Partial): Partial +>sample : Partial +} +declare let cafoo: ObjectContaining<{ a: number, foo: number }>; +>cafoo : ObjectContaining<{ a: number; foo: number; }> +>a : number +>foo : number + +declare let cfoo: ObjectContaining; +>cfoo : ObjectContaining + +cfoo = cafoo; +>cfoo = cafoo : ObjectContaining<{ a: number; foo: number; }> +>cfoo : ObjectContaining +>cafoo : ObjectContaining<{ a: number; foo: number; }> + +cafoo = cfoo; +>cafoo = cfoo : ObjectContaining +>cafoo : ObjectContaining<{ a: number; foo: number; }> +>cfoo : ObjectContaining + diff --git a/tests/baselines/reference/recursiveTypeComparison.errors.txt b/tests/baselines/reference/recursiveTypeComparison.errors.txt deleted file mode 100644 index f647763b2e275..0000000000000 --- a/tests/baselines/reference/recursiveTypeComparison.errors.txt +++ /dev/null @@ -1,27 +0,0 @@ -tests/cases/compiler/recursiveTypeComparison.ts(14,5): error TS2322: Type 'Observable<{}>' is not assignable to type 'Property'. - Types of property 'needThisOne' are incompatible. - Type 'Observable<{}>' is not assignable to type 'Observable'. - Type '{}' is not assignable to type 'number'. - - -==== tests/cases/compiler/recursiveTypeComparison.ts (1 errors) ==== - // Before fix this would take an exceeding long time to complete (#1170) - - interface Observable { - // This member can't be of type T, Property, or Observable - needThisOne: Observable; - // Add more to make it slower - expo1: Property; // 0.31 seconds in check - expo2: Property; // 3.11 seconds - expo3: Property; // 82.28 seconds - } - interface Property extends Observable { } - - var p: Observable<{}>; - var stuck: Property = p; - ~~~~~ -!!! error TS2322: Type 'Observable<{}>' is not assignable to type 'Property'. -!!! error TS2322: Types of property 'needThisOne' are incompatible. -!!! error TS2322: Type 'Observable<{}>' is not assignable to type 'Observable'. -!!! error TS2322: Type '{}' is not assignable to type 'number'. - \ No newline at end of file diff --git a/tests/baselines/reference/specedNoStackBlown.js b/tests/baselines/reference/specedNoStackBlown.js new file mode 100644 index 0000000000000..034caf4d7eba8 --- /dev/null +++ b/tests/baselines/reference/specedNoStackBlown.js @@ -0,0 +1,47 @@ +//// [specedNoStackBlown.ts] +// Type definitions for spected 0.7 +// Project: https://github.com/25th-floor/spected +// Definitions by: Benjamin Makus +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +declare function spected = SpecValue>(spec: SPEC, input: ROOTINPUT): Result; + +type Predicate = (value: INPUT, inputs: ROOTINPUT) => boolean; + +type ErrorMsg = + | (string | number | boolean | symbol | null | undefined | object) + | ((value: INPUT, field: string) => any); + +export type Spec = [Predicate, ErrorMsg]; + +export type SpecArray = Array>; + +export type SpecFunction = [INPUT] extends [ReadonlyArray] + ? (value: INPUT) => ReadonlyArray> + : [INPUT] extends [object] + ? (value: INPUT) => SpecObject + : (value: INPUT) => SpecArray; + +export type SpecObject = Partial<{[key in keyof INPUT]: SpecValue}>; + +export type SpecValue = [INPUT] extends [ReadonlyArray] + ? SpecArray | SpecFunction + : [INPUT] extends [object] + ? SpecArray | SpecFunction | SpecObject + : SpecArray | SpecFunction; + +export type Result = {[key in keyof INPUT]: true | any[] | Result}; + +export default spected; + + +//// [specedNoStackBlown.js] +"use strict"; +// Type definitions for spected 0.7 +// Project: https://github.com/25th-floor/spected +// Definitions by: Benjamin Makus +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 +exports.__esModule = true; +exports["default"] = spected; diff --git a/tests/baselines/reference/specedNoStackBlown.symbols b/tests/baselines/reference/specedNoStackBlown.symbols new file mode 100644 index 0000000000000..299e31e98082c --- /dev/null +++ b/tests/baselines/reference/specedNoStackBlown.symbols @@ -0,0 +1,158 @@ +=== tests/cases/compiler/specedNoStackBlown.ts === +// Type definitions for spected 0.7 +// Project: https://github.com/25th-floor/spected +// Definitions by: Benjamin Makus +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +declare function spected = SpecValue>(spec: SPEC, input: ROOTINPUT): Result; +>spected : Symbol(spected, Decl(specedNoStackBlown.ts, 0, 0)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 6, 25)) +>SPEC : Symbol(SPEC, Decl(specedNoStackBlown.ts, 6, 35)) +>SpecValue : Symbol(SpecValue, Decl(specedNoStackBlown.ts, 24, 115)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 6, 25)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 6, 25)) +>SpecValue : Symbol(SpecValue, Decl(specedNoStackBlown.ts, 24, 115)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 6, 25)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 6, 25)) +>spec : Symbol(spec, Decl(specedNoStackBlown.ts, 6, 116)) +>SPEC : Symbol(SPEC, Decl(specedNoStackBlown.ts, 6, 35)) +>input : Symbol(input, Decl(specedNoStackBlown.ts, 6, 127)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 6, 25)) +>Result : Symbol(Result, Decl(specedNoStackBlown.ts, 30, 75)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 6, 25)) +>SPEC : Symbol(SPEC, Decl(specedNoStackBlown.ts, 6, 35)) + +type Predicate = (value: INPUT, inputs: ROOTINPUT) => boolean; +>Predicate : Symbol(Predicate, Decl(specedNoStackBlown.ts, 6, 171)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 8, 15)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 8, 21)) +>value : Symbol(value, Decl(specedNoStackBlown.ts, 8, 36)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 8, 15)) +>inputs : Symbol(inputs, Decl(specedNoStackBlown.ts, 8, 49)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 8, 21)) + +type ErrorMsg = +>ErrorMsg : Symbol(ErrorMsg, Decl(specedNoStackBlown.ts, 8, 80)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 10, 14)) + + | (string | number | boolean | symbol | null | undefined | object) + | ((value: INPUT, field: string) => any); +>value : Symbol(value, Decl(specedNoStackBlown.ts, 12, 8)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 10, 14)) +>field : Symbol(field, Decl(specedNoStackBlown.ts, 12, 21)) + +export type Spec = [Predicate, ErrorMsg]; +>Spec : Symbol(Spec, Decl(specedNoStackBlown.ts, 12, 45)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 14, 17)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 14, 23)) +>Predicate : Symbol(Predicate, Decl(specedNoStackBlown.ts, 6, 171)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 14, 17)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 14, 23)) +>ErrorMsg : Symbol(ErrorMsg, Decl(specedNoStackBlown.ts, 8, 80)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 14, 17)) + +export type SpecArray = Array>; +>SpecArray : Symbol(SpecArray, Decl(specedNoStackBlown.ts, 14, 90)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 16, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 16, 28)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Spec : Symbol(Spec, Decl(specedNoStackBlown.ts, 12, 45)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 16, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 16, 28)) + +export type SpecFunction = [INPUT] extends [ReadonlyArray] +>SpecFunction : Symbol(SpecFunction, Decl(specedNoStackBlown.ts, 16, 78)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 18, 25)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 18, 31)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 18, 25)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) +>U : Symbol(U, Decl(specedNoStackBlown.ts, 18, 87)) + + ? (value: INPUT) => ReadonlyArray> +>value : Symbol(value, Decl(specedNoStackBlown.ts, 19, 7)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 18, 25)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) +>SpecArray : Symbol(SpecArray, Decl(specedNoStackBlown.ts, 14, 90)) +>U : Symbol(U, Decl(specedNoStackBlown.ts, 18, 87)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 18, 31)) + + : [INPUT] extends [object] +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 18, 25)) + + ? (value: INPUT) => SpecObject +>value : Symbol(value, Decl(specedNoStackBlown.ts, 21, 11)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 18, 25)) +>SpecObject : Symbol(SpecObject, Decl(specedNoStackBlown.ts, 22, 56)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 18, 25)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 18, 31)) + + : (value: INPUT) => SpecArray; +>value : Symbol(value, Decl(specedNoStackBlown.ts, 22, 11)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 18, 25)) +>SpecArray : Symbol(SpecArray, Decl(specedNoStackBlown.ts, 14, 90)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 18, 25)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 18, 31)) + +export type SpecObject = Partial<{[key in keyof INPUT]: SpecValue}>; +>SpecObject : Symbol(SpecObject, Decl(specedNoStackBlown.ts, 22, 56)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 24, 23)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 24, 29)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>key : Symbol(key, Decl(specedNoStackBlown.ts, 24, 59)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 24, 23)) +>SpecValue : Symbol(SpecValue, Decl(specedNoStackBlown.ts, 24, 115)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 24, 23)) +>key : Symbol(key, Decl(specedNoStackBlown.ts, 24, 59)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 24, 29)) + +export type SpecValue = [INPUT] extends [ReadonlyArray] +>SpecValue : Symbol(SpecValue, Decl(specedNoStackBlown.ts, 24, 115)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 26, 28)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + + ? SpecArray | SpecFunction +>SpecArray : Symbol(SpecArray, Decl(specedNoStackBlown.ts, 14, 90)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 26, 28)) +>SpecFunction : Symbol(SpecFunction, Decl(specedNoStackBlown.ts, 16, 78)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 26, 28)) + + : [INPUT] extends [object] +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) + + ? SpecArray | SpecFunction | SpecObject +>SpecArray : Symbol(SpecArray, Decl(specedNoStackBlown.ts, 14, 90)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 26, 28)) +>SpecFunction : Symbol(SpecFunction, Decl(specedNoStackBlown.ts, 16, 78)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 26, 28)) +>SpecObject : Symbol(SpecObject, Decl(specedNoStackBlown.ts, 22, 56)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 26, 28)) + + : SpecArray | SpecFunction; +>SpecArray : Symbol(SpecArray, Decl(specedNoStackBlown.ts, 14, 90)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 26, 28)) +>SpecFunction : Symbol(SpecFunction, Decl(specedNoStackBlown.ts, 16, 78)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 26, 22)) +>ROOTINPUT : Symbol(ROOTINPUT, Decl(specedNoStackBlown.ts, 26, 28)) + +export type Result = {[key in keyof INPUT]: true | any[] | Result}; +>Result : Symbol(Result, Decl(specedNoStackBlown.ts, 30, 75)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 32, 19)) +>SPEC : Symbol(SPEC, Decl(specedNoStackBlown.ts, 32, 25)) +>key : Symbol(key, Decl(specedNoStackBlown.ts, 32, 36)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 32, 19)) +>Result : Symbol(Result, Decl(specedNoStackBlown.ts, 30, 75)) +>INPUT : Symbol(INPUT, Decl(specedNoStackBlown.ts, 32, 19)) +>key : Symbol(key, Decl(specedNoStackBlown.ts, 32, 36)) + +export default spected; +>spected : Symbol(spected, Decl(specedNoStackBlown.ts, 0, 0)) + diff --git a/tests/baselines/reference/specedNoStackBlown.types b/tests/baselines/reference/specedNoStackBlown.types new file mode 100644 index 0000000000000..654f98941df1a --- /dev/null +++ b/tests/baselines/reference/specedNoStackBlown.types @@ -0,0 +1,64 @@ +=== tests/cases/compiler/specedNoStackBlown.ts === +// Type definitions for spected 0.7 +// Project: https://github.com/25th-floor/spected +// Definitions by: Benjamin Makus +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +declare function spected = SpecValue>(spec: SPEC, input: ROOTINPUT): Result; +>spected : = SpecValue>(spec: SPEC, input: ROOTINPUT) => Result +>spec : SPEC +>input : ROOTINPUT + +type Predicate = (value: INPUT, inputs: ROOTINPUT) => boolean; +>Predicate : Predicate +>value : INPUT +>inputs : ROOTINPUT + +type ErrorMsg = +>ErrorMsg : ErrorMsg + + | (string | number | boolean | symbol | null | undefined | object) +>null : null + + | ((value: INPUT, field: string) => any); +>value : INPUT +>field : string + +export type Spec = [Predicate, ErrorMsg]; +>Spec : [Predicate, ErrorMsg] + +export type SpecArray = Array>; +>SpecArray : [Predicate, ErrorMsg][] + +export type SpecFunction = [INPUT] extends [ReadonlyArray] +>SpecFunction : SpecFunction + + ? (value: INPUT) => ReadonlyArray> +>value : INPUT + + : [INPUT] extends [object] + ? (value: INPUT) => SpecObject +>value : INPUT + + : (value: INPUT) => SpecArray; +>value : INPUT + +export type SpecObject = Partial<{[key in keyof INPUT]: SpecValue}>; +>SpecObject : Partial<{ [key in keyof INPUT]: SpecValue; }> + +export type SpecValue = [INPUT] extends [ReadonlyArray] +>SpecValue : SpecValue + + ? SpecArray | SpecFunction + : [INPUT] extends [object] + ? SpecArray | SpecFunction | SpecObject + : SpecArray | SpecFunction; + +export type Result = {[key in keyof INPUT]: true | any[] | Result}; +>Result : Result +>true : true + +export default spected; +>spected : = SpecValue>(spec: SPEC, input: ROOTINPUT) => Result + diff --git a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt index 3ff04c44fb75b..d24b88a7a94cf 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt +++ b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt @@ -62,13 +62,9 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(84,1): error TS2322: Type 'Fun tests/cases/compiler/strictFunctionTypesErrors.ts(111,1): error TS2322: Type 'Comparer2' is not assignable to type 'Comparer2'. Property 'dog' is missing in type 'Animal' but required in type 'Dog'. tests/cases/compiler/strictFunctionTypesErrors.ts(126,1): error TS2322: Type 'Crate' is not assignable to type 'Crate'. - Types of property 'onSetItem' are incompatible. - Type '(item: Dog) => void' is not assignable to type '(item: Animal) => void'. - Types of parameters 'item' and 'item' are incompatible. - Type 'Animal' is not assignable to type 'Dog'. + Type 'Animal' is not assignable to type 'Dog'. tests/cases/compiler/strictFunctionTypesErrors.ts(127,1): error TS2322: Type 'Crate' is not assignable to type 'Crate'. - Types of property 'item' are incompatible. - Type 'Animal' is not assignable to type 'Dog'. + Type 'Animal' is not assignable to type 'Dog'. tests/cases/compiler/strictFunctionTypesErrors.ts(133,1): error TS2322: Type '(f: (x: Dog) => Dog) => void' is not assignable to type '(f: (x: Animal) => Animal) => void'. Types of parameters 'f' and 'f' are incompatible. Type 'Animal' is not assignable to type 'Dog'. @@ -308,15 +304,11 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(155,5): error TS2322: Type '(c animalCrate = dogCrate; // Error ~~~~~~~~~~~ !!! error TS2322: Type 'Crate' is not assignable to type 'Crate'. -!!! error TS2322: Types of property 'onSetItem' are incompatible. -!!! error TS2322: Type '(item: Dog) => void' is not assignable to type '(item: Animal) => void'. -!!! error TS2322: Types of parameters 'item' and 'item' are incompatible. -!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. +!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. dogCrate = animalCrate; // Error ~~~~~~~~ !!! error TS2322: Type 'Crate' is not assignable to type 'Crate'. -!!! error TS2322: Types of property 'item' are incompatible. -!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. +!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. // Verify that callback parameters are strictly checked diff --git a/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.errors.txt b/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.errors.txt deleted file mode 100644 index 47f97958f0d53..0000000000000 --- a/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.errors.txt +++ /dev/null @@ -1,82 +0,0 @@ -tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.ts(63,6): error TS2345: Argument of type 'NeededInfo>' is not assignable to parameter of type 'NeededInfo<{}>'. - Types of property 'ASchema' are incompatible. - Type 'ToA>' is not assignable to type 'ToA<{}>'. - Type '{}' is not assignable to type 'ToB<{ initialize: any; }>'. -tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.ts(66,38): error TS2344: Type 'NeededInfo>' does not satisfy the constraint 'NeededInfo<{}>'. - - -==== tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.ts (2 errors) ==== - type Either = Left | Right; - - class Left { - readonly _tag: 'Left' = 'Left' - readonly _A!: A - readonly _L!: L - constructor(readonly value: L) {} - /** The given function is applied if this is a `Right` */ - map(f: (a: A) => B): Either { - return this as any - } - ap(fab: Either B>): Either { - return null as any - } - } - - class Right { - readonly _tag: 'Right' = 'Right' - readonly _A!: A - readonly _L!: L - constructor(readonly value: A) {} - map(f: (a: A) => B): Either { - return new Right(f(this.value)) - } - ap(fab: Either B>): Either { - return null as any; - } - } - - class Type { - readonly _A!: A; - readonly _O!: O; - readonly _I!: I; - constructor( - /** a unique name for this codec */ - readonly name: string, - /** a custom type guard */ - readonly is: (u: unknown) => u is A, - /** succeeds if a value of type I can be decoded to a value of type A */ - readonly validate: (input: I, context: {}[]) => Either<{}[], A>, - /** converts a value of type A to a value of type O */ - readonly encode: (a: A) => O - ) {} - /** a version of `validate` with a default context */ - decode(i: I): Either<{}[], A> { return null as any; } - } - - interface Any extends Type {} - - type TypeOf = C["_A"]; - - type ToB = { [k in keyof S]: TypeOf }; - type ToA = { [k in keyof S]: Type }; - - type NeededInfo = { - ASchema: ToA; - }; - - export type MyInfo = NeededInfo>; - - const tmp1: MyInfo = null!; - function tmp2(n: N) {} - tmp2(tmp1); // uncommenting this line removes a type error from a completely unrelated line ?? - ~~~~ -!!! error TS2345: Argument of type 'NeededInfo>' is not assignable to parameter of type 'NeededInfo<{}>'. -!!! error TS2345: Types of property 'ASchema' are incompatible. -!!! error TS2345: Type 'ToA>' is not assignable to type 'ToA<{}>'. -!!! error TS2345: Type '{}' is not assignable to type 'ToB<{ initialize: any; }>'. -!!! related TS2728 tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.ts:59:39: 'initialize' is declared here. - - class Server {} - export class MyServer extends Server {} // not assignable error at `MyInfo` - ~~~~~~ -!!! error TS2344: Type 'NeededInfo>' does not satisfy the constraint 'NeededInfo<{}>'. \ No newline at end of file diff --git a/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.types b/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.types index d360372d5aaee..f6342d442ee2f 100644 --- a/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.types +++ b/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.types @@ -155,7 +155,7 @@ function tmp2(n: N) {} >n : N tmp2(tmp1); // uncommenting this line removes a type error from a completely unrelated line ?? ->tmp2(tmp1) : any +>tmp2(tmp1) : void >tmp2 : >(n: N) => void >tmp1 : NeededInfo> diff --git a/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign2.errors.txt b/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign2.errors.txt deleted file mode 100644 index aba1bc1db66d9..0000000000000 --- a/tests/baselines/reference/varianceProblingAndZeroOrderIndexSignatureRelationsAlign2.errors.txt +++ /dev/null @@ -1,79 +0,0 @@ -tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign2.ts(66,38): error TS2344: Type 'NeededInfo>' does not satisfy the constraint 'NeededInfo<{}>'. - Types of property 'ASchema' are incompatible. - Type 'ToA>' is not assignable to type 'ToA<{}>'. - Type '{}' is not assignable to type 'ToB<{ initialize: any; }>'. - - -==== tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign2.ts (1 errors) ==== - type Either = Left | Right; - - class Left { - readonly _tag: 'Left' = 'Left' - readonly _A!: A - readonly _L!: L - constructor(readonly value: L) {} - /** The given function is applied if this is a `Right` */ - map(f: (a: A) => B): Either { - return this as any - } - ap(fab: Either B>): Either { - return null as any - } - } - - class Right { - readonly _tag: 'Right' = 'Right' - readonly _A!: A - readonly _L!: L - constructor(readonly value: A) {} - map(f: (a: A) => B): Either { - return new Right(f(this.value)) - } - ap(fab: Either B>): Either { - return null as any; - } - } - - class Type { - readonly _A!: A; - readonly _O!: O; - readonly _I!: I; - constructor( - /** a unique name for this codec */ - readonly name: string, - /** a custom type guard */ - readonly is: (u: unknown) => u is A, - /** succeeds if a value of type I can be decoded to a value of type A */ - readonly validate: (input: I, context: {}[]) => Either<{}[], A>, - /** converts a value of type A to a value of type O */ - readonly encode: (a: A) => O - ) {} - /** a version of `validate` with a default context */ - decode(i: I): Either<{}[], A> { return null as any; } - } - - interface Any extends Type {} - - type TypeOf = C["_A"]; - - type ToB = { [k in keyof S]: TypeOf }; - type ToA = { [k in keyof S]: Type }; - - type NeededInfo = { - ASchema: ToA; - }; - - export type MyInfo = NeededInfo>; - - const tmp1: MyInfo = null!; - function tmp2(n: N) {} - // tmp2(tmp1); // uncommenting this line removes a type error from a completely unrelated line ?? (see test 1, needs to behave the same) - - class Server {} - export class MyServer extends Server {} // not assignable error at `MyInfo` - ~~~~~~ -!!! error TS2344: Type 'NeededInfo>' does not satisfy the constraint 'NeededInfo<{}>'. -!!! error TS2344: Types of property 'ASchema' are incompatible. -!!! error TS2344: Type 'ToA>' is not assignable to type 'ToA<{}>'. -!!! error TS2344: Type '{}' is not assignable to type 'ToB<{ initialize: any; }>'. -!!! related TS2728 tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign2.ts:59:39: 'initialize' is declared here. \ No newline at end of file diff --git a/tests/cases/compiler/nongenericPartialInstantiationsRelatedInBothDirections.ts b/tests/cases/compiler/nongenericPartialInstantiationsRelatedInBothDirections.ts new file mode 100644 index 0000000000000..ece5187738c60 --- /dev/null +++ b/tests/cases/compiler/nongenericPartialInstantiationsRelatedInBothDirections.ts @@ -0,0 +1,12 @@ +interface Foo { + a: number; + b: number; + bar: string; +} +interface ObjectContaining { + new (sample: Partial): Partial +} +declare let cafoo: ObjectContaining<{ a: number, foo: number }>; +declare let cfoo: ObjectContaining; +cfoo = cafoo; +cafoo = cfoo; diff --git a/tests/cases/compiler/specedNoStackBlown.ts b/tests/cases/compiler/specedNoStackBlown.ts new file mode 100644 index 0000000000000..9ada3ce1c55a9 --- /dev/null +++ b/tests/cases/compiler/specedNoStackBlown.ts @@ -0,0 +1,35 @@ +// Type definitions for spected 0.7 +// Project: https://github.com/25th-floor/spected +// Definitions by: Benjamin Makus +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +declare function spected = SpecValue>(spec: SPEC, input: ROOTINPUT): Result; + +type Predicate = (value: INPUT, inputs: ROOTINPUT) => boolean; + +type ErrorMsg = + | (string | number | boolean | symbol | null | undefined | object) + | ((value: INPUT, field: string) => any); + +export type Spec = [Predicate, ErrorMsg]; + +export type SpecArray = Array>; + +export type SpecFunction = [INPUT] extends [ReadonlyArray] + ? (value: INPUT) => ReadonlyArray> + : [INPUT] extends [object] + ? (value: INPUT) => SpecObject + : (value: INPUT) => SpecArray; + +export type SpecObject = Partial<{[key in keyof INPUT]: SpecValue}>; + +export type SpecValue = [INPUT] extends [ReadonlyArray] + ? SpecArray | SpecFunction + : [INPUT] extends [object] + ? SpecArray | SpecFunction | SpecObject + : SpecArray | SpecFunction; + +export type Result = {[key in keyof INPUT]: true | any[] | Result}; + +export default spected;