Fixed an issue with not being able to use mapped type over union constraint as rest param (#49947)

This commit is contained in:
Mateusz Burzyński
2023-03-20 19:14:25 +01:00
committed by GitHub
parent 27aca613ff
commit 1ed06e6b05
11 changed files with 429 additions and 3 deletions

View File

@@ -13861,7 +13861,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const typeVariable = getHomomorphicTypeVariable(type);
if (typeVariable && !type.declaration.nameType) {
const constraint = getConstraintOfTypeParameter(typeVariable);
if (constraint && isArrayType(constraint)) {
if (constraint && everyType(constraint, isArrayOrTupleType)) {
return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper));
}
}
@@ -21686,7 +21686,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return varianceResult;
}
}
else if (isReadonlyArrayType(target) ? isArrayOrTupleType(source) : isArrayType(target) && isTupleType(source) && !source.target.readonly) {
else if (isReadonlyArrayType(target) ? everyType(source, isArrayOrTupleType) : isArrayType(target) && everyType(source, t => isTupleType(t) && !t.target.readonly)) {
if (relation !== identityRelation) {
return isRelatedTo(getIndexTypeOfType(source, numberType) || anyType, getIndexTypeOfType(target, numberType) || anyType, RecursionFlags.Both, reportErrors);
}
@@ -29258,7 +29258,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
getContextualType(node, contextFlags);
const instantiatedType = instantiateContextualType(contextualType, node, contextFlags);
if (instantiatedType && !(contextFlags && contextFlags & ContextFlags.NoConstraints && instantiatedType.flags & TypeFlags.TypeVariable)) {
const apparentType = mapType(instantiatedType, getApparentType, /*noReductions*/ true);
const apparentType = mapType(
instantiatedType,
// When obtaining apparent type of *contextual* type we don't want to get apparent type of mapped types.
// That would evaluate mapped types with array or tuple type constraints too eagerly
// and thus it would prevent `getTypeOfPropertyOfContextualType` from obtaining per-position contextual type for elements of array literal expressions.
// Apparent type of other mapped types is already the mapped type itself so we can just avoid calling `getApparentType` here for all mapped types.
t => getObjectFlags(t) & ObjectFlags.Mapped ? t : getApparentType(t),
/*noReductions*/ true
);
return apparentType.flags & TypeFlags.Union && isObjectLiteralExpression(node) ? discriminateContextualTypeByObjectMembers(node, apparentType as UnionType) :
apparentType.flags & TypeFlags.Union && isJsxAttributes(node) ? discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType) :
apparentType;

View File

@@ -0,0 +1,134 @@
=== tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts ===
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390594
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
>Writeable : Symbol(Writeable, Decl(mappedTypeTupleConstraintAssignability.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 15))
>P : Symbol(P, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 33))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 15))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 15))
>P : Symbol(P, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 33))
type EnumValues = [string, ...string[]];
>EnumValues : Symbol(EnumValues, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 55))
type Values<T extends EnumValues> = { [k in T[number]]: k; };
>Values : Symbol(Values, Decl(mappedTypeTupleConstraintAssignability.ts, 3, 40))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 12))
>EnumValues : Symbol(EnumValues, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 55))
>k : Symbol(k, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 39))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 12))
>k : Symbol(k, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 39))
declare class ZodEnum<T extends [string, ...string[]]> {
>ZodEnum : Symbol(ZodEnum, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 61))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 6, 22))
get enum(): Values<T>
>enum : Symbol(ZodEnum.enum, Decl(mappedTypeTupleConstraintAssignability.ts, 6, 56))
>Values : Symbol(Values, Decl(mappedTypeTupleConstraintAssignability.ts, 3, 40))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 6, 22))
}
declare function createZodEnum<U extends string, T extends Readonly<[U, ...U[]]>>(values: T): ZodEnum<Writeable<T>>;
>createZodEnum : Symbol(createZodEnum, Decl(mappedTypeTupleConstraintAssignability.ts, 8, 1))
>U : Symbol(U, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 31))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 48))
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
>U : Symbol(U, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 31))
>U : Symbol(U, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 31))
>values : Symbol(values, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 82))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 48))
>ZodEnum : Symbol(ZodEnum, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 61))
>Writeable : Symbol(Writeable, Decl(mappedTypeTupleConstraintAssignability.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 48))
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390607
type Maybe<T> = T | null | undefined;
>Maybe : Symbol(Maybe, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 116))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 11))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 11))
type AnyTuple = [unknown, ...unknown[]];
>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37))
type AnyObject = { [k: string]: any };
>AnyObject : Symbol(AnyObject, Decl(mappedTypeTupleConstraintAssignability.ts, 15, 40))
>k : Symbol(k, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 20))
type Flags = "s" | "d" | "";
>Flags : Symbol(Flags, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 38))
interface ISchema<T, C = any, F extends Flags = any, D = any> {
>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 18))
>C : Symbol(C, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 20))
>F : Symbol(F, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 29))
>Flags : Symbol(Flags, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 38))
>D : Symbol(D, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 52))
__flags: F;
>__flags : Symbol(ISchema.__flags, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 63))
>F : Symbol(F, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 29))
__context: C;
>__context : Symbol(ISchema.__context, Decl(mappedTypeTupleConstraintAssignability.ts, 20, 13))
>C : Symbol(C, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 20))
__outputType: T;
>__outputType : Symbol(ISchema.__outputType, Decl(mappedTypeTupleConstraintAssignability.ts, 21, 15))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 18))
__default: D;
>__default : Symbol(ISchema.__default, Decl(mappedTypeTupleConstraintAssignability.ts, 22, 18))
>D : Symbol(D, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 52))
}
declare class TupleSchema<
>TupleSchema : Symbol(TupleSchema, Decl(mappedTypeTupleConstraintAssignability.ts, 24, 1))
TType extends Maybe<AnyTuple> = AnyTuple | undefined,
>TType : Symbol(TType, Decl(mappedTypeTupleConstraintAssignability.ts, 26, 26))
>Maybe : Symbol(Maybe, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 116))
>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37))
>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37))
TContext = AnyObject,
>TContext : Symbol(TContext, Decl(mappedTypeTupleConstraintAssignability.ts, 27, 55))
>AnyObject : Symbol(AnyObject, Decl(mappedTypeTupleConstraintAssignability.ts, 15, 40))
TDefault = undefined,
>TDefault : Symbol(TDefault, Decl(mappedTypeTupleConstraintAssignability.ts, 28, 23))
TFlags extends Flags = ""
>TFlags : Symbol(TFlags, Decl(mappedTypeTupleConstraintAssignability.ts, 29, 23))
>Flags : Symbol(Flags, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 38))
> {
constructor(schemas: [ISchema<any>, ...ISchema<any>[]]);
>schemas : Symbol(schemas, Decl(mappedTypeTupleConstraintAssignability.ts, 32, 14))
>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28))
>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28))
}
export function create<T extends AnyTuple>(schemas: {
>create : Symbol(create, Decl(mappedTypeTupleConstraintAssignability.ts, 33, 1))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23))
>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37))
>schemas : Symbol(schemas, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 43))
[K in keyof T]: ISchema<T[K]>;
>K : Symbol(K, Decl(mappedTypeTupleConstraintAssignability.ts, 36, 3))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23))
>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23))
>K : Symbol(K, Decl(mappedTypeTupleConstraintAssignability.ts, 36, 3))
}) {
return new TupleSchema<T | undefined>(schemas);
>TupleSchema : Symbol(TupleSchema, Decl(mappedTypeTupleConstraintAssignability.ts, 24, 1))
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23))
>schemas : Symbol(schemas, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 43))
}

View File

@@ -0,0 +1,76 @@
=== tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts ===
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390594
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
>Writeable : Writeable<T>
type EnumValues = [string, ...string[]];
>EnumValues : [string, ...string[]]
type Values<T extends EnumValues> = { [k in T[number]]: k; };
>Values : Values<T>
declare class ZodEnum<T extends [string, ...string[]]> {
>ZodEnum : ZodEnum<T>
get enum(): Values<T>
>enum : Values<T>
}
declare function createZodEnum<U extends string, T extends Readonly<[U, ...U[]]>>(values: T): ZodEnum<Writeable<T>>;
>createZodEnum : <U extends string, T extends readonly [U, ...U[]]>(values: T) => ZodEnum<Writeable<T>>
>values : T
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390607
type Maybe<T> = T | null | undefined;
>Maybe : Maybe<T>
type AnyTuple = [unknown, ...unknown[]];
>AnyTuple : [unknown, ...unknown[]]
type AnyObject = { [k: string]: any };
>AnyObject : { [k: string]: any; }
>k : string
type Flags = "s" | "d" | "";
>Flags : "" | "s" | "d"
interface ISchema<T, C = any, F extends Flags = any, D = any> {
__flags: F;
>__flags : F
__context: C;
>__context : C
__outputType: T;
>__outputType : T
__default: D;
>__default : D
}
declare class TupleSchema<
>TupleSchema : TupleSchema<TType, TContext, TDefault, TFlags>
TType extends Maybe<AnyTuple> = AnyTuple | undefined,
TContext = AnyObject,
TDefault = undefined,
TFlags extends Flags = ""
> {
constructor(schemas: [ISchema<any>, ...ISchema<any>[]]);
>schemas : [ISchema<any, any, any, any>, ...ISchema<any, any, any, any>[]]
}
export function create<T extends AnyTuple>(schemas: {
>create : <T extends AnyTuple>(schemas: { [K in keyof T]: ISchema<T[K], any, any, any>; }) => TupleSchema<T | undefined, AnyObject, undefined, "">
>schemas : { [K in keyof T]: ISchema<T[K], any, any, any>; }
[K in keyof T]: ISchema<T[K]>;
}) {
return new TupleSchema<T | undefined>(schemas);
>new TupleSchema<T | undefined>(schemas) : TupleSchema<T | undefined, AnyObject, undefined, "">
>TupleSchema : typeof TupleSchema
>schemas : { [K in keyof T]: ISchema<T[K], any, any, any>; }
}

View File

@@ -0,0 +1,18 @@
tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts(9,9): error TS2322: Type 'HomomorphicMappedType<T>' is not assignable to type 'any[]'.
==== tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts (1 errors) ====
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
function test1<T extends [number] | [string]>(args: T) {
const arr: any[] = [] as HomomorphicMappedType<T>
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
}
function test2<T extends [number] | readonly [string]>(args: T) {
const arr: any[] = [] as HomomorphicMappedType<T> // error
~~~
!!! error TS2322: Type 'HomomorphicMappedType<T>' is not assignable to type 'any[]'.
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
}

View File

@@ -0,0 +1,43 @@
=== tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts ===
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 27))
>P : Symbol(P, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 35))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 27))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 27))
>P : Symbol(P, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 35))
function test1<T extends [number] | [string]>(args: T) {
>test1 : Symbol(test1, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 88))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15))
>args : Symbol(args, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 46))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15))
const arr: any[] = [] as HomomorphicMappedType<T>
>arr : Symbol(arr, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 3, 7))
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15))
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
>arr2 : Symbol(arr2, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 4, 7))
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15))
}
function test2<T extends [number] | readonly [string]>(args: T) {
>test2 : Symbol(test2, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 5, 1))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15))
>args : Symbol(args, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 55))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15))
const arr: any[] = [] as HomomorphicMappedType<T> // error
>arr : Symbol(arr, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 8, 7))
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15))
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
>arr2 : Symbol(arr2, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 9, 7))
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15))
}

View File

@@ -0,0 +1,34 @@
=== tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts ===
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
>HomomorphicMappedType : HomomorphicMappedType<T>
function test1<T extends [number] | [string]>(args: T) {
>test1 : <T extends [number] | [string]>(args: T) => void
>args : T
const arr: any[] = [] as HomomorphicMappedType<T>
>arr : any[]
>[] as HomomorphicMappedType<T> : HomomorphicMappedType<T>
>[] : []
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
>arr2 : readonly any[]
>[] as HomomorphicMappedType<T> : HomomorphicMappedType<T>
>[] : []
}
function test2<T extends [number] | readonly [string]>(args: T) {
>test2 : <T extends [number] | readonly [string]>(args: T) => void
>args : T
const arr: any[] = [] as HomomorphicMappedType<T> // error
>arr : any[]
>[] as HomomorphicMappedType<T> : HomomorphicMappedType<T>
>[] : []
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
>arr2 : readonly any[]
>[] as HomomorphicMappedType<T> : HomomorphicMappedType<T>
>[] : []
}

View File

@@ -0,0 +1,27 @@
=== tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts ===
// repro 29919#issuecomment-470948453
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0))
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 27))
>P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 35))
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 27))
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 27))
>P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 35))
declare function test<T extends [number] | [string]>(
>test : Symbol(test, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 88))
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22))
args: T,
>args : Symbol(args, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 53))
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22))
fn: (...args: HomomorphicMappedType<T>) => void
>fn : Symbol(fn, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 5, 10))
>args : Symbol(args, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 6, 7))
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0))
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22))
): void

View File

@@ -0,0 +1,18 @@
=== tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts ===
// repro 29919#issuecomment-470948453
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
>HomomorphicMappedType : HomomorphicMappedType<T>
declare function test<T extends [number] | [string]>(
>test : <T extends [number] | [string]>(args: T, fn: (...args: HomomorphicMappedType<T>) => void) => void
args: T,
>args : T
fn: (...args: HomomorphicMappedType<T>) => void
>fn : (...args: HomomorphicMappedType<T>) => void
>args : HomomorphicMappedType<T>
): void

View File

@@ -0,0 +1,43 @@
// @strict: true
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390594
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
type EnumValues = [string, ...string[]];
type Values<T extends EnumValues> = { [k in T[number]]: k; };
declare class ZodEnum<T extends [string, ...string[]]> {
get enum(): Values<T>
}
declare function createZodEnum<U extends string, T extends Readonly<[U, ...U[]]>>(values: T): ZodEnum<Writeable<T>>;
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390607
type Maybe<T> = T | null | undefined;
type AnyTuple = [unknown, ...unknown[]];
type AnyObject = { [k: string]: any };
type Flags = "s" | "d" | "";
interface ISchema<T, C = any, F extends Flags = any, D = any> {
__flags: F;
__context: C;
__outputType: T;
__default: D;
}
declare class TupleSchema<
TType extends Maybe<AnyTuple> = AnyTuple | undefined,
TContext = AnyObject,
TDefault = undefined,
TFlags extends Flags = ""
> {
constructor(schemas: [ISchema<any>, ...ISchema<any>[]]);
}
export function create<T extends AnyTuple>(schemas: {
[K in keyof T]: ISchema<T[K]>;
}) {
return new TupleSchema<T | undefined>(schemas);
}

View File

@@ -0,0 +1,14 @@
// @noEmit: true
// @strict: true
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
function test1<T extends [number] | [string]>(args: T) {
const arr: any[] = [] as HomomorphicMappedType<T>
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
}
function test2<T extends [number] | readonly [string]>(args: T) {
const arr: any[] = [] as HomomorphicMappedType<T> // error
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
}

View File

@@ -0,0 +1,11 @@
// @noEmit: true
// @strict: true
// repro 29919#issuecomment-470948453
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
declare function test<T extends [number] | [string]>(
args: T,
fn: (...args: HomomorphicMappedType<T>) => void
): void