Skip to content

Commit

Permalink
Mapped type support for array subtypes, like microsoft#26063
Browse files Browse the repository at this point in the history
  • Loading branch information
jablko committed Feb 13, 2020
1 parent 98492d8 commit f4ae733
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 32 deletions.
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13657,8 +13657,8 @@ namespace ts {
return mapType(mappedTypeVariable, t => {
if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && t !== errorType) {
const replacementMapper = createReplacementMapper(typeVariable, t, mapper);
return isArrayType(t) ? instantiateMappedArrayType(t, type, replacementMapper) :
isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) :
return isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) :
t.flags & (TypeFlags.Object | TypeFlags.Intersection) && isArrayLikeType(t) ? instantiateMappedArrayType(t, type, replacementMapper) :
instantiateAnonymousType(type, replacementMapper);
}
return t;
Expand Down

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion tests/baselines/reference/keyofAndIndexedAccess2.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts(67,3): error TS232
tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts(68,3): error TS2322: Type '123' is not assignable to type 'T[K]'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts(108,5): error TS2322: Type '123' is not assignable to type 'Type[K]'.
Type '123' is not assignable to type 'never'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts(115,21): error TS2313: Type parameter 'Q' has a circular constraint.


==== tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts (23 errors) ====
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts (24 errors) ====
function f1(obj: { a: number, b: 0 | 1, c: string }, k0: 'a', k1: 'a' | 'b', k2: 'a' | 'b' | 'c') {
obj[k0] = 1;
obj[k0] = 2;
Expand Down Expand Up @@ -195,6 +196,9 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts(108,5): error TS23
type StrictExtract<T, U> = T extends U ? U extends T ? T : never : never;
type StrictExclude<T, U> = T extends StrictExtract<T, U> ? never : T;
type A<T> = { [Q in { [P in keyof T]: P; }[keyof T]]: T[Q]; };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2313: Type parameter 'Q' has a circular constraint.
!!! related TS2751 tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts:116:36: Circularity originates in type at this location.
type B<T, V> = A<{ [Q in keyof T]: StrictExclude<B<T[Q], V>, {}>; }>;

// Repros from #30938
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/keyofAndIndexedAccess2.types
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ type A<T> = { [Q in { [P in keyof T]: P; }[keyof T]]: T[Q]; };
>A : A<T>

type B<T, V> = A<{ [Q in keyof T]: StrictExclude<B<T[Q], V>, {}>; }>;
>B : A<{ [Q in keyof T]: StrictExclude<A<{ [Q in keyof T[Q]]: StrictExclude<A<{ [Q in keyof T[Q][Q]]: StrictExclude<A<{ [Q in keyof T[Q][Q][Q]]: StrictExclude<A<{ [Q in keyof T[Q][Q][Q][Q]]: StrictExclude<A<{ [Q in keyof T[Q][Q][Q][Q][Q]]: StrictExclude<A<{ [Q in keyof T[Q][Q][Q][Q][Q][Q]]: StrictExclude<A<{ [Q in keyof T[Q][Q][Q][Q][Q][Q][Q]]: StrictExclude<A<{ [Q in keyof T[Q][Q][Q][Q][Q][Q][Q][Q]]: StrictExclude<A<{ [Q in keyof T[Q][Q][Q][Q][Q][Q][Q][Q][Q]]: StrictExclude<A<{ [Q in keyof T[Q][Q][Q][Q][Q][Q][Q][Q][Q][Q]]: StrictExclude<A<any>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>
>B : A<{ [Q in keyof T]: never; }>

// Repros from #30938

Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/ramdaToolsNoInfinite.types
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,14 @@ declare namespace Curry {
};

type Gaps<T extends any[]> = CleanedGaps<PartialGaps<T>>;
>Gaps : CleanedGaps<PartialGaps<T>>
>Gaps : NonNullable<PartialGaps<T>[number]>[]

type Curry<F extends ((...args: any) => any)> =
>Curry : Curry<F>
>args : any

<T extends any[]>(...args: Tools.Cast<Tools.Cast<T, Gaps<Parameters<F>>>, any[]>) =>
>args : Tools.Cast<Tools.Cast<T, CleanedGaps<PartialGaps<Parameters<F>>>>, any[]>
>args : Tools.Cast<Tools.Cast<T, NonNullable<PartialGaps<Parameters<F>>[number]>[]>, any[]>
>Tools : any
>Tools : any

Expand Down

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions tests/baselines/reference/specedNoStackBlown.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
tests/cases/compiler/specedNoStackBlown.ts(7,50): error TS2315: Type 'SpecValue' is not generic.
tests/cases/compiler/specedNoStackBlown.ts(7,84): error TS2315: Type 'SpecValue' is not generic.
tests/cases/compiler/specedNoStackBlown.ts(22,29): error TS2315: Type 'SpecObject' is not generic.
tests/cases/compiler/specedNoStackBlown.ts(25,13): error TS2456: Type alias 'SpecObject' circularly references itself.
tests/cases/compiler/specedNoStackBlown.ts(25,81): error TS2315: Type 'SpecValue' is not generic.
tests/cases/compiler/specedNoStackBlown.ts(27,13): error TS2456: Type alias 'SpecValue' circularly references itself.
tests/cases/compiler/specedNoStackBlown.ts(30,78): error TS2315: Type 'SpecObject' is not generic.


==== tests/cases/compiler/specedNoStackBlown.ts (7 errors) ====
// 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>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2315: Type 'SpecValue' is not generic.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2315: Type 'SpecValue' is not generic.

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>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2315: Type 'SpecObject' is not generic.
: (value: INPUT) => SpecArray<INPUT, ROOTINPUT>;

export type SpecObject<INPUT, ROOTINPUT = any> = Partial<{[key in keyof INPUT]: SpecValue<INPUT[key], ROOTINPUT>}>;
~~~~~~~~~~
!!! error TS2456: Type alias 'SpecObject' circularly references itself.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2315: Type 'SpecValue' is not generic.

export type SpecValue<INPUT, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<any>]
~~~~~~~~~
!!! error TS2456: Type alias 'SpecValue' circularly references itself.
? SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>
: [INPUT] extends [object]
? SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT> | SpecObject<INPUT, ROOTINPUT>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2315: Type 'SpecObject' is not generic.
: SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>;

export type Result<INPUT, SPEC> = {[key in keyof INPUT]: true | any[] | Result<INPUT[key], any>};

export default spected;

8 changes: 4 additions & 4 deletions tests/baselines/reference/specedNoStackBlown.types
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// 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>
>spected : <ROOTINPUT, SPEC extends any = any>(spec: SPEC, input: ROOTINPUT) => Result<ROOTINPUT, SPEC>
>spec : SPEC
>input : ROOTINPUT

Expand Down Expand Up @@ -45,10 +45,10 @@ export type SpecFunction<INPUT, ROOTINPUT = any> = [INPUT] extends [ReadonlyArra
>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>; }>
>SpecObject : any

export type SpecValue<INPUT, ROOTINPUT = any> = [INPUT] extends [ReadonlyArray<any>]
>SpecValue : SpecValue<INPUT, ROOTINPUT>
>SpecValue : any

? SpecArray<INPUT, ROOTINPUT> | SpecFunction<INPUT, ROOTINPUT>
: [INPUT] extends [object]
Expand All @@ -60,5 +60,5 @@ export type Result<INPUT, SPEC> = {[key in keyof INPUT]: true | any[] | Result<I
>true : true

export default spected;
>spected : <ROOTINPUT, SPEC extends SpecValue<ROOTINPUT, ROOTINPUT> = SpecValue<ROOTINPUT, ROOTINPUT>>(spec: SPEC, input: ROOTINPUT) => Result<ROOTINPUT, SPEC>
>spected : <ROOTINPUT, SPEC extends any = any>(spec: SPEC, input: ROOTINPUT) => Result<ROOTINPUT, SPEC>

0 comments on commit f4ae733

Please sign in to comment.