mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-10 21:07:52 -05:00
Use identity with the permissive instantation to detect nongenric instances and disable variance probing on nongeneric instances (#29981)
* Use identity with the restrictive instantation to detect nongenric instances and disable variance probing on nongeneric instances * Generalize to also include interfaces, add test case, still perform argument comparisons for postive comparisons if possible * Actually accept baselines, lol * Reduce deep nesting limit just a bit so yargs still builds * Handle circular identities in isNonGeneric * Use a simple traversal of the types rather than the restrictive instantiation * Cache the bits using an existing field to further reduce any time nongeneric check takes * Revert to using an existing mapper, use permissive > restrictive * Revert constant change * And revert the comment, too
This commit is contained in:
@@ -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<Type> | undefined, targetTypeArguments: ReadonlyArray<Type> | 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
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
tests/cases/compiler/checkInfiniteExpansionTermination.ts(16,1): error TS2322: Type 'ISubject<Bar>' is not assignable to type 'IObservable<Foo>'.
|
||||
Types of property 'n' are incompatible.
|
||||
Type 'IObservable<Bar[]>' is not assignable to type 'IObservable<Foo[]>'.
|
||||
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<T> {
|
||||
n: IObservable<T[]>; // Needed, must be T[]
|
||||
}
|
||||
|
||||
// Needed
|
||||
interface ISubject<T> extends IObservable<T> { }
|
||||
|
||||
interface Foo { x }
|
||||
interface Bar { y }
|
||||
|
||||
var values: IObservable<Foo>;
|
||||
var values2: ISubject<Bar>;
|
||||
values = values2;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type 'ISubject<Bar>' is not assignable to type 'IObservable<Foo>'.
|
||||
!!! error TS2322: Types of property 'n' are incompatible.
|
||||
!!! error TS2322: Type 'IObservable<Bar[]>' is not assignable to type 'IObservable<Foo[]>'.
|
||||
!!! 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.
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
tests/cases/compiler/invariantGenericErrorElaboration.ts(3,7): error TS2322: Type 'Num' is not assignable to type 'Runtype<any>'.
|
||||
Types of property 'constraint' are incompatible.
|
||||
Type 'Constraint<Num>' is not assignable to type 'Constraint<Runtype<any>>'.
|
||||
Types of property 'constraint' are incompatible.
|
||||
Type 'Constraint<Constraint<Num>>' is not assignable to type 'Constraint<Constraint<Runtype<any>>>'.
|
||||
Types of property 'constraint' are incompatible.
|
||||
Type 'Constraint<Constraint<Constraint<Num>>>' is not assignable to type 'Constraint<Constraint<Constraint<Runtype<any>>>>'.
|
||||
Type 'Constraint<Constraint<Runtype<any>>>' is not assignable to type 'Constraint<Constraint<Num>>'.
|
||||
Types of property 'underlying' are incompatible.
|
||||
Type 'Constraint<Runtype<any>>' is not assignable to type 'Constraint<Num>'.
|
||||
tests/cases/compiler/invariantGenericErrorElaboration.ts(4,19): error TS2322: Type 'Num' is not assignable to type 'Runtype<any>'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/invariantGenericErrorElaboration.ts (2 errors) ====
|
||||
// Repro from #19746
|
||||
|
||||
const wat: Runtype<any> = Num;
|
||||
~~~
|
||||
!!! error TS2322: Type 'Num' is not assignable to type 'Runtype<any>'.
|
||||
!!! error TS2322: Types of property 'constraint' are incompatible.
|
||||
!!! error TS2322: Type 'Constraint<Num>' is not assignable to type 'Constraint<Runtype<any>>'.
|
||||
!!! error TS2322: Types of property 'constraint' are incompatible.
|
||||
!!! error TS2322: Type 'Constraint<Constraint<Num>>' is not assignable to type 'Constraint<Constraint<Runtype<any>>>'.
|
||||
!!! error TS2322: Types of property 'constraint' are incompatible.
|
||||
!!! error TS2322: Type 'Constraint<Constraint<Constraint<Num>>>' is not assignable to type 'Constraint<Constraint<Constraint<Runtype<any>>>>'.
|
||||
!!! error TS2322: Type 'Constraint<Constraint<Runtype<any>>>' is not assignable to type 'Constraint<Constraint<Num>>'.
|
||||
!!! error TS2322: Types of property 'underlying' are incompatible.
|
||||
!!! error TS2322: Type 'Constraint<Runtype<any>>' is not assignable to type 'Constraint<Num>'.
|
||||
!!! 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<any>'.
|
||||
!!! related TS6501 tests/cases/compiler/invariantGenericErrorElaboration.ts:17:34: The expected type comes from this index signature.
|
||||
|
||||
interface Runtype<A> {
|
||||
constraint: Constraint<this>
|
||||
witness: A
|
||||
}
|
||||
|
||||
interface Num extends Runtype<number> {
|
||||
tag: 'number'
|
||||
}
|
||||
declare const Num: Num
|
||||
|
||||
interface Obj<O extends { [_ in string]: Runtype<any> }> extends Runtype<{[K in keyof O]: O[K]['witness'] }> {}
|
||||
declare function Obj<O extends { [_: string]: Runtype<any> }>(fields: O): Obj<O>;
|
||||
|
||||
interface Constraint<A extends Runtype<any>> extends Runtype<A['witness']> {
|
||||
underlying: A,
|
||||
check: (x: A['witness']) => void,
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ const wat: Runtype<any> = 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 : <O extends { [_: string]: Runtype<any>; }>(fields: O) => Obj<O>
|
||||
>{ foo: Num } : { foo: Num; }
|
||||
>foo : Num
|
||||
|
||||
@@ -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<U>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(72,5): error TS2322: Type 'Partial<T>' is not assignable to type 'T'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(78,5): error TS2322: Type 'Partial<Thing>' is not assignable to type 'Partial<T>'.
|
||||
Type 'Thing' is not assignable to type 'T'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(88,5): error TS2322: Type 'Readonly<Thing>' is not assignable to type 'Readonly<T>'.
|
||||
Type 'Thing' is not assignable to type 'T'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(127,5): error TS2322: Type 'Partial<U>' is not assignable to type 'Identity<U>'.
|
||||
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<Thing>' is not assignable to type 'Partial<T>'.
|
||||
!!! error TS2322: Type 'Thing' is not assignable to type 'T'.
|
||||
}
|
||||
|
||||
function f40<T>(x: T, y: Readonly<T>) {
|
||||
@@ -212,7 +209,6 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
|
||||
y = x; // Error
|
||||
~
|
||||
!!! error TS2322: Type 'Readonly<Thing>' is not assignable to type 'Readonly<T>'.
|
||||
!!! error TS2322: Type 'Thing' is not assignable to type 'T'.
|
||||
}
|
||||
|
||||
type Item = {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//// [nongenericPartialInstantiationsRelatedInBothDirections.ts]
|
||||
interface Foo {
|
||||
a: number;
|
||||
b: number;
|
||||
bar: string;
|
||||
}
|
||||
interface ObjectContaining<T> {
|
||||
new (sample: Partial<T>): Partial<T>
|
||||
}
|
||||
declare let cafoo: ObjectContaining<{ a: number, foo: number }>;
|
||||
declare let cfoo: ObjectContaining<Foo>;
|
||||
cfoo = cafoo;
|
||||
cafoo = cfoo;
|
||||
|
||||
|
||||
//// [nongenericPartialInstantiationsRelatedInBothDirections.js]
|
||||
cfoo = cafoo;
|
||||
cafoo = cfoo;
|
||||
@@ -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<T> {
|
||||
>ObjectContaining : Symbol(ObjectContaining, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 4, 1))
|
||||
>T : Symbol(T, Decl(nongenericPartialInstantiationsRelatedInBothDirections.ts, 5, 27))
|
||||
|
||||
new (sample: Partial<T>): Partial<T>
|
||||
>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<Foo>;
|
||||
>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))
|
||||
|
||||
@@ -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<T> {
|
||||
new (sample: Partial<T>): Partial<T>
|
||||
>sample : Partial<T>
|
||||
}
|
||||
declare let cafoo: ObjectContaining<{ a: number, foo: number }>;
|
||||
>cafoo : ObjectContaining<{ a: number; foo: number; }>
|
||||
>a : number
|
||||
>foo : number
|
||||
|
||||
declare let cfoo: ObjectContaining<Foo>;
|
||||
>cfoo : ObjectContaining<Foo>
|
||||
|
||||
cfoo = cafoo;
|
||||
>cfoo = cafoo : ObjectContaining<{ a: number; foo: number; }>
|
||||
>cfoo : ObjectContaining<Foo>
|
||||
>cafoo : ObjectContaining<{ a: number; foo: number; }>
|
||||
|
||||
cafoo = cfoo;
|
||||
>cafoo = cfoo : ObjectContaining<Foo>
|
||||
>cafoo : ObjectContaining<{ a: number; foo: number; }>
|
||||
>cfoo : ObjectContaining<Foo>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
tests/cases/compiler/recursiveTypeComparison.ts(14,5): error TS2322: Type 'Observable<{}>' is not assignable to type 'Property<number>'.
|
||||
Types of property 'needThisOne' are incompatible.
|
||||
Type 'Observable<{}>' is not assignable to type 'Observable<number>'.
|
||||
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<T> {
|
||||
// This member can't be of type T, Property<T>, or Observable<anything but T>
|
||||
needThisOne: Observable<T>;
|
||||
// Add more to make it slower
|
||||
expo1: Property<T[]>; // 0.31 seconds in check
|
||||
expo2: Property<T[]>; // 3.11 seconds
|
||||
expo3: Property<T[]>; // 82.28 seconds
|
||||
}
|
||||
interface Property<T> extends Observable<T> { }
|
||||
|
||||
var p: Observable<{}>;
|
||||
var stuck: Property<number> = p;
|
||||
~~~~~
|
||||
!!! error TS2322: Type 'Observable<{}>' is not assignable to type 'Property<number>'.
|
||||
!!! error TS2322: Types of property 'needThisOne' are incompatible.
|
||||
!!! error TS2322: Type 'Observable<{}>' is not assignable to type 'Observable<number>'.
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'number'.
|
||||
|
||||
47
tests/baselines/reference/specedNoStackBlown.js
Normal file
47
tests/baselines/reference/specedNoStackBlown.js
Normal file
@@ -0,0 +1,47 @@
|
||||
//// [specedNoStackBlown.ts]
|
||||
// Type definitions for spected 0.7
|
||||
// Project: https://github.com/25th-floor/spected
|
||||
// Definitions by: Benjamin Makus <https://github.com/benneq>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.8
|
||||
|
||||
declare function spected<ROOTINPUT, SPEC extends SpecValue<ROOTINPUT, ROOTINPUT> = SpecValue<ROOTINPUT, ROOTINPUT>>(spec: SPEC, input: ROOTINPUT): Result<ROOTINPUT, SPEC>;
|
||||
|
||||
type Predicate<INPUT, ROOTINPUT> = (value: INPUT, inputs: ROOTINPUT) => boolean;
|
||||
|
||||
type ErrorMsg<INPUT> =
|
||||
| (string | number | boolean | symbol | null | undefined | object)
|
||||
| ((value: INPUT, field: string) => any);
|
||||
|
||||
export type Spec<INPUT, ROOTINPUT = any> = [Predicate<INPUT, ROOTINPUT>, ErrorMsg<INPUT>];
|
||||
|
||||
export type SpecArray<INPUT, ROOTINPUT = any> = Array<Spec<INPUT, ROOTINPUT>>;
|
||||
|
||||
export type SpecFunction<INPUT, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<infer U>]
|
||||
? (value: INPUT) => ReadonlyArray<SpecArray<U, ROOTINPUT>>
|
||||
: [INPUT] extends [object]
|
||||
? (value: INPUT) => SpecObject<INPUT, ROOTINPUT>
|
||||
: (value: INPUT) => SpecArray<INPUT, ROOTINPUT>;
|
||||
|
||||
export type SpecObject<INPUT, ROOTINPUT = any> = Partial<{[key in keyof INPUT]: SpecValue<INPUT[key], ROOTINPUT>}>;
|
||||
|
||||
export type SpecValue<INPUT, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<any>]
|
||||
? SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>
|
||||
: [INPUT] extends [object]
|
||||
? SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT> | SpecObject<INPUT, ROOTINPUT>
|
||||
: SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>;
|
||||
|
||||
export type Result<INPUT, SPEC> = {[key in keyof INPUT]: true | any[] | Result<INPUT[key], any>};
|
||||
|
||||
export default spected;
|
||||
|
||||
|
||||
//// [specedNoStackBlown.js]
|
||||
"use strict";
|
||||
// Type definitions for spected 0.7
|
||||
// Project: https://github.com/25th-floor/spected
|
||||
// Definitions by: Benjamin Makus <https://github.com/benneq>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.8
|
||||
exports.__esModule = true;
|
||||
exports["default"] = spected;
|
||||
158
tests/baselines/reference/specedNoStackBlown.symbols
Normal file
158
tests/baselines/reference/specedNoStackBlown.symbols
Normal file
@@ -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 <https://github.com/benneq>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.8
|
||||
|
||||
declare function spected<ROOTINPUT, SPEC extends SpecValue<ROOTINPUT, ROOTINPUT> = SpecValue<ROOTINPUT, ROOTINPUT>>(spec: SPEC, input: ROOTINPUT): Result<ROOTINPUT, SPEC>;
|
||||
>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<INPUT, ROOTINPUT> = (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<INPUT> =
|
||||
>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<INPUT, ROOTINPUT = any> = [Predicate<INPUT, ROOTINPUT>, ErrorMsg<INPUT>];
|
||||
>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<INPUT, ROOTINPUT = any> = Array<Spec<INPUT, ROOTINPUT>>;
|
||||
>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, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<infer U>]
|
||||
>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<SpecArray<U, ROOTINPUT>>
|
||||
>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<INPUT, ROOTINPUT>
|
||||
>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<INPUT, ROOTINPUT>;
|
||||
>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<INPUT, ROOTINPUT = any> = Partial<{[key in keyof INPUT]: SpecValue<INPUT[key], ROOTINPUT>}>;
|
||||
>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, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<any>]
|
||||
>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<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>
|
||||
>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<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT> | SpecObject<INPUT, ROOTINPUT>
|
||||
>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<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>;
|
||||
>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<INPUT, SPEC> = {[key in keyof INPUT]: true | any[] | Result<INPUT[key], any>};
|
||||
>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))
|
||||
|
||||
64
tests/baselines/reference/specedNoStackBlown.types
Normal file
64
tests/baselines/reference/specedNoStackBlown.types
Normal file
@@ -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 <https://github.com/benneq>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.8
|
||||
|
||||
declare function spected<ROOTINPUT, SPEC extends SpecValue<ROOTINPUT, ROOTINPUT> = SpecValue<ROOTINPUT, ROOTINPUT>>(spec: SPEC, input: ROOTINPUT): Result<ROOTINPUT, SPEC>;
|
||||
>spected : <ROOTINPUT, SPEC extends SpecValue<ROOTINPUT, ROOTINPUT> = SpecValue<ROOTINPUT, ROOTINPUT>>(spec: SPEC, input: ROOTINPUT) => Result<ROOTINPUT, SPEC>
|
||||
>spec : SPEC
|
||||
>input : ROOTINPUT
|
||||
|
||||
type Predicate<INPUT, ROOTINPUT> = (value: INPUT, inputs: ROOTINPUT) => boolean;
|
||||
>Predicate : Predicate<INPUT, ROOTINPUT>
|
||||
>value : INPUT
|
||||
>inputs : ROOTINPUT
|
||||
|
||||
type ErrorMsg<INPUT> =
|
||||
>ErrorMsg : ErrorMsg<INPUT>
|
||||
|
||||
| (string | number | boolean | symbol | null | undefined | object)
|
||||
>null : null
|
||||
|
||||
| ((value: INPUT, field: string) => any);
|
||||
>value : INPUT
|
||||
>field : string
|
||||
|
||||
export type Spec<INPUT, ROOTINPUT = any> = [Predicate<INPUT, ROOTINPUT>, ErrorMsg<INPUT>];
|
||||
>Spec : [Predicate<INPUT, ROOTINPUT>, ErrorMsg<INPUT>]
|
||||
|
||||
export type SpecArray<INPUT, ROOTINPUT = any> = Array<Spec<INPUT, ROOTINPUT>>;
|
||||
>SpecArray : [Predicate<INPUT, ROOTINPUT>, ErrorMsg<INPUT>][]
|
||||
|
||||
export type SpecFunction<INPUT, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<infer U>]
|
||||
>SpecFunction : SpecFunction<INPUT, ROOTINPUT>
|
||||
|
||||
? (value: INPUT) => ReadonlyArray<SpecArray<U, ROOTINPUT>>
|
||||
>value : INPUT
|
||||
|
||||
: [INPUT] extends [object]
|
||||
? (value: INPUT) => SpecObject<INPUT, ROOTINPUT>
|
||||
>value : INPUT
|
||||
|
||||
: (value: INPUT) => SpecArray<INPUT, ROOTINPUT>;
|
||||
>value : INPUT
|
||||
|
||||
export type SpecObject<INPUT, ROOTINPUT = any> = Partial<{[key in keyof INPUT]: SpecValue<INPUT[key], ROOTINPUT>}>;
|
||||
>SpecObject : Partial<{ [key in keyof INPUT]: SpecValue<INPUT[key], ROOTINPUT>; }>
|
||||
|
||||
export type SpecValue<INPUT, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<any>]
|
||||
>SpecValue : SpecValue<INPUT, ROOTINPUT>
|
||||
|
||||
? SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>
|
||||
: [INPUT] extends [object]
|
||||
? SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT> | SpecObject<INPUT, ROOTINPUT>
|
||||
: SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>;
|
||||
|
||||
export type Result<INPUT, SPEC> = {[key in keyof INPUT]: true | any[] | Result<INPUT[key], any>};
|
||||
>Result : Result<INPUT, SPEC>
|
||||
>true : true
|
||||
|
||||
export default spected;
|
||||
>spected : <ROOTINPUT, SPEC extends SpecValue<ROOTINPUT, ROOTINPUT> = SpecValue<ROOTINPUT, ROOTINPUT>>(spec: SPEC, input: ROOTINPUT) => Result<ROOTINPUT, SPEC>
|
||||
|
||||
@@ -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<Dog>' is not assignable to type 'Comparer2<Animal>'.
|
||||
Property 'dog' is missing in type 'Animal' but required in type 'Dog'.
|
||||
tests/cases/compiler/strictFunctionTypesErrors.ts(126,1): error TS2322: Type 'Crate<Dog>' is not assignable to type 'Crate<Animal>'.
|
||||
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<Animal>' is not assignable to type 'Crate<Dog>'.
|
||||
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<Dog>' is not assignable to type 'Crate<Animal>'.
|
||||
!!! 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<Animal>' is not assignable to type 'Crate<Dog>'.
|
||||
!!! 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
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.ts(63,6): error TS2345: Argument of type 'NeededInfo<ToB<{ initialize: any; }>>' is not assignable to parameter of type 'NeededInfo<{}>'.
|
||||
Types of property 'ASchema' are incompatible.
|
||||
Type 'ToA<ToB<{ initialize: any; }>>' 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<ToB<{ initialize: any; }>>' does not satisfy the constraint 'NeededInfo<{}>'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign.ts (2 errors) ====
|
||||
type Either<L, A> = Left<L, A> | Right<L, A>;
|
||||
|
||||
class Left<L, A> {
|
||||
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<B>(f: (a: A) => B): Either<L, B> {
|
||||
return this as any
|
||||
}
|
||||
ap<B>(fab: Either<L, (a: A) => B>): Either<L, B> {
|
||||
return null as any
|
||||
}
|
||||
}
|
||||
|
||||
class Right<L, A> {
|
||||
readonly _tag: 'Right' = 'Right'
|
||||
readonly _A!: A
|
||||
readonly _L!: L
|
||||
constructor(readonly value: A) {}
|
||||
map<B>(f: (a: A) => B): Either<L, B> {
|
||||
return new Right(f(this.value))
|
||||
}
|
||||
ap<B>(fab: Either<L, (a: A) => B>): Either<L, B> {
|
||||
return null as any;
|
||||
}
|
||||
}
|
||||
|
||||
class Type<A, O = A, I = unknown> {
|
||||
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<any, any, any> {}
|
||||
|
||||
type TypeOf<C extends Any> = C["_A"];
|
||||
|
||||
type ToB<S extends any> = { [k in keyof S]: TypeOf<S[k]> };
|
||||
type ToA<S> = { [k in keyof S]: Type<S[k]> };
|
||||
|
||||
type NeededInfo<MyNamespaceSchema = {}> = {
|
||||
ASchema: ToA<MyNamespaceSchema>;
|
||||
};
|
||||
|
||||
export type MyInfo = NeededInfo<ToB<{ initialize: any }>>;
|
||||
|
||||
const tmp1: MyInfo = null!;
|
||||
function tmp2<N extends NeededInfo>(n: N) {}
|
||||
tmp2(tmp1); // uncommenting this line removes a type error from a completely unrelated line ??
|
||||
~~~~
|
||||
!!! error TS2345: Argument of type 'NeededInfo<ToB<{ initialize: any; }>>' is not assignable to parameter of type 'NeededInfo<{}>'.
|
||||
!!! error TS2345: Types of property 'ASchema' are incompatible.
|
||||
!!! error TS2345: Type 'ToA<ToB<{ initialize: any; }>>' 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<X extends NeededInfo> {}
|
||||
export class MyServer extends Server<MyInfo> {} // not assignable error at `MyInfo`
|
||||
~~~~~~
|
||||
!!! error TS2344: Type 'NeededInfo<ToB<{ initialize: any; }>>' does not satisfy the constraint 'NeededInfo<{}>'.
|
||||
@@ -155,7 +155,7 @@ function tmp2<N extends NeededInfo>(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 extends NeededInfo<{}>>(n: N) => void
|
||||
>tmp1 : NeededInfo<ToB<{ initialize: any; }>>
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign2.ts(66,38): error TS2344: Type 'NeededInfo<ToB<{ initialize: any; }>>' does not satisfy the constraint 'NeededInfo<{}>'.
|
||||
Types of property 'ASchema' are incompatible.
|
||||
Type 'ToA<ToB<{ initialize: any; }>>' is not assignable to type 'ToA<{}>'.
|
||||
Type '{}' is not assignable to type 'ToB<{ initialize: any; }>'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/varianceProblingAndZeroOrderIndexSignatureRelationsAlign2.ts (1 errors) ====
|
||||
type Either<L, A> = Left<L, A> | Right<L, A>;
|
||||
|
||||
class Left<L, A> {
|
||||
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<B>(f: (a: A) => B): Either<L, B> {
|
||||
return this as any
|
||||
}
|
||||
ap<B>(fab: Either<L, (a: A) => B>): Either<L, B> {
|
||||
return null as any
|
||||
}
|
||||
}
|
||||
|
||||
class Right<L, A> {
|
||||
readonly _tag: 'Right' = 'Right'
|
||||
readonly _A!: A
|
||||
readonly _L!: L
|
||||
constructor(readonly value: A) {}
|
||||
map<B>(f: (a: A) => B): Either<L, B> {
|
||||
return new Right(f(this.value))
|
||||
}
|
||||
ap<B>(fab: Either<L, (a: A) => B>): Either<L, B> {
|
||||
return null as any;
|
||||
}
|
||||
}
|
||||
|
||||
class Type<A, O = A, I = unknown> {
|
||||
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<any, any, any> {}
|
||||
|
||||
type TypeOf<C extends Any> = C["_A"];
|
||||
|
||||
type ToB<S extends any> = { [k in keyof S]: TypeOf<S[k]> };
|
||||
type ToA<S> = { [k in keyof S]: Type<S[k]> };
|
||||
|
||||
type NeededInfo<MyNamespaceSchema = {}> = {
|
||||
ASchema: ToA<MyNamespaceSchema>;
|
||||
};
|
||||
|
||||
export type MyInfo = NeededInfo<ToB<{ initialize: any }>>;
|
||||
|
||||
const tmp1: MyInfo = null!;
|
||||
function tmp2<N extends NeededInfo>(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<X extends NeededInfo> {}
|
||||
export class MyServer extends Server<MyInfo> {} // not assignable error at `MyInfo`
|
||||
~~~~~~
|
||||
!!! error TS2344: Type 'NeededInfo<ToB<{ initialize: any; }>>' does not satisfy the constraint 'NeededInfo<{}>'.
|
||||
!!! error TS2344: Types of property 'ASchema' are incompatible.
|
||||
!!! error TS2344: Type 'ToA<ToB<{ initialize: any; }>>' 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.
|
||||
@@ -0,0 +1,12 @@
|
||||
interface Foo {
|
||||
a: number;
|
||||
b: number;
|
||||
bar: string;
|
||||
}
|
||||
interface ObjectContaining<T> {
|
||||
new (sample: Partial<T>): Partial<T>
|
||||
}
|
||||
declare let cafoo: ObjectContaining<{ a: number, foo: number }>;
|
||||
declare let cfoo: ObjectContaining<Foo>;
|
||||
cfoo = cafoo;
|
||||
cafoo = cfoo;
|
||||
35
tests/cases/compiler/specedNoStackBlown.ts
Normal file
35
tests/cases/compiler/specedNoStackBlown.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
// Type definitions for spected 0.7
|
||||
// Project: https://github.com/25th-floor/spected
|
||||
// Definitions by: Benjamin Makus <https://github.com/benneq>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.8
|
||||
|
||||
declare function spected<ROOTINPUT, SPEC extends SpecValue<ROOTINPUT, ROOTINPUT> = SpecValue<ROOTINPUT, ROOTINPUT>>(spec: SPEC, input: ROOTINPUT): Result<ROOTINPUT, SPEC>;
|
||||
|
||||
type Predicate<INPUT, ROOTINPUT> = (value: INPUT, inputs: ROOTINPUT) => boolean;
|
||||
|
||||
type ErrorMsg<INPUT> =
|
||||
| (string | number | boolean | symbol | null | undefined | object)
|
||||
| ((value: INPUT, field: string) => any);
|
||||
|
||||
export type Spec<INPUT, ROOTINPUT = any> = [Predicate<INPUT, ROOTINPUT>, ErrorMsg<INPUT>];
|
||||
|
||||
export type SpecArray<INPUT, ROOTINPUT = any> = Array<Spec<INPUT, ROOTINPUT>>;
|
||||
|
||||
export type SpecFunction<INPUT, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<infer U>]
|
||||
? (value: INPUT) => ReadonlyArray<SpecArray<U, ROOTINPUT>>
|
||||
: [INPUT] extends [object]
|
||||
? (value: INPUT) => SpecObject<INPUT, ROOTINPUT>
|
||||
: (value: INPUT) => SpecArray<INPUT, ROOTINPUT>;
|
||||
|
||||
export type SpecObject<INPUT, ROOTINPUT = any> = Partial<{[key in keyof INPUT]: SpecValue<INPUT[key], ROOTINPUT>}>;
|
||||
|
||||
export type SpecValue<INPUT, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<any>]
|
||||
? SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>
|
||||
: [INPUT] extends [object]
|
||||
? SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT> | SpecObject<INPUT, ROOTINPUT>
|
||||
: SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>;
|
||||
|
||||
export type Result<INPUT, SPEC> = {[key in keyof INPUT]: true | any[] | Result<INPUT[key], any>};
|
||||
|
||||
export default spected;
|
||||
Reference in New Issue
Block a user