🔎 Search Terms
Mapped Types, Satisfying Constraints, Recursive Type Mapping, TypeScript 7, RC
🕗 Version & Regression Information
This changed between versions
Between 6.0.3 and 7.0.1-rc
This changed in commit or PR
Unknown. However I recall things were working ok approximately 2 weeks ago. The update may be recent.
- This is the behavior in every version I tried
Tested 4.9.5 through to 6.0.3. Problem is specific to 7.0.1-rc
⏯ Playground Link
https://www.typescriptlang.org/play/?target=99&module=7&ts=4.9.5#code/JYWwDg9gTgLgBALzgMyhEcDkCIBNMBQBA9MXALSVXU2130ONMlkCSAdqgIYDOMUAVwDGMAVACmLCkxmy58ouIAekWHBgBPMOLgAVAMpCAFuJBc4AXjgBvdVvEAuOHyjB2AczgBfRSujxNbT0AeTAYYAh2LgAbAB5dezhlGHF2XB49QxMzS0zjUy4APlyEoIAyGywAPwgwiKjozCd+AR0fAmVVeDcUqGQuIR1dACVxZFjR5CSlFLSMlzd3YuTU9Lzs81sCODttJ0xJzAAaOG24CWQnSdOfTv84HvE+gaH9fkXp2bWDfJytncCjiwb1cHkwN18XV2QwACmhtLBgOIMlZRkJoLhYnDak9NABpcQaE4-DaFSH3R7PQYhABGACtxCIsfDcUiMis5npsQjwsjljNVhkSQUbGdAftgvTGTBCDswCzEcinNzWciCO1SNJ5NqddqpABZLhgMCLKS680WhgEQFwABaeFKOisCAAdOiJC79OhxI6iDbdAAxNAgSaxADCkRSM0+gq5Ct5PBO1w5awWHmKVgAFGdkwLOQBrQkQKYR9hRmBnHYAfj0QfQjvDkeSJ1L5YA2pMALpknY7Jyu+24ABy4gAbk8CABKa2JQPBlWwDSNsvJGOc3QLhPExIpoVZApHM4AdWAMCMjrXa0HF6sc-r9mX5e32kKh52J7PoXCkRil4y18SW8dzzb4v3qX8awHPAwJ-OIP3PexiiceDHUPDM4HgmCGj9Wc6xASUGSZVtV13OMcUVRM4E3Nk-zInk2TfOBNUNY1xFwPRElGdwJB4Hh6jgAAJJ5JB2Ugzk1YJ8ycHYADYXQABhdABmcSyADLhgGiJwAHYFJdABGcgoCEVTVLgABRKA0CgJwL0wWw2wJDQHnYOBCw0YsqPjNlO2VbzkUcwlO1osyQjqWD4n3MxihrQcsJieI8IbYiZhOaiAqc7tijgF1ctynNkQEaJ4FIgCgmdF04qlJlrErOBAuctw3KLKZ0p4Xza3neMlxSmA0v8ngGu7M4vDJdDRh4IqKxnII7xAEEPgqwcFo8HDZqSh9etojcBufHRSOFaLcmzHYLwOgjpViNxkCeLzyITba2pizr0Auoim1Su76L5OAHDOM6QKFUNrtu3Mvnmd50zgGs5tDXqkzGJD-uA8HMkhzwYbwlbPD+nYoOHMcJ2nM1LVJ0mpAAVR4Lh3EkTUyYZ801p0DgwAEeBbzemBYlqnYlFs0NMAAQUwV8zg0AWxliYXRcYhBJfGGWyVGmadGCdm2Y5l6QAbWxe01G11ZgTXcnxrmebOIXbOx3tbbtu3NT5-tKrwbGAG51ROVn2ey+2-YdsgdglxAXdwd26v9yP-cdxBneW9GPajpPo7ILwTldd1xBdAASBYwDJIA
💻 Code
The following code will fault on 7.0.1-rc
The issue relates to the TFromObject mapping where it's not possible to satisfy the left side ZodType constraint. The issue is specific to resolving a foreign TRef<T> on a remote Context object.
import z from 'zod'
// ------------------------------------------------------------------
// Infrastructure
// ------------------------------------------------------------------
export type TSchema = { type: string }
export type TOptional<Type extends TSchema = TSchema> = Type & { '~optional': true }
export interface TRef<Ref extends string> extends TSchema {
type: 'Ref',
ref: Ref
}
export interface TString extends TSchema {
type: 'String'
}
export type TProperties = Record<PropertyKey, TSchema>
export interface TObject<Properties extends TProperties> extends TSchema {
type: 'Object'
properties: Properties
}
// ------------------------------------------------------------------
// Mapping
// ------------------------------------------------------------------
type ZodType = z.core.SomeType
type TFromRef<Context extends TProperties, Ref extends string> = (
Ref extends keyof Context
? TFromType<Context, Context[Ref]>
: z.ZodNever
)
type TFromProperty<Context extends TProperties, Type extends TSchema,
WithType extends ZodType = TFromType<Context, Type>,
WithOptional extends ZodType = Type extends TOptional ? z.ZodOptional<WithType> : WithType,
> = WithOptional
type TFromObject<Context extends TProperties, Properties extends TProperties,
// Mapped Type Regression Here
//
// Ok: 6.0.3
// Fail: 7.0.1-rc
//
// Error: Type '{ [Key in keyof Properties]: Properties[Key] extends
// TOptional<TSchema> ? ZodOptional<TFromType<Context, Properties[Key]>> .....
Result extends ZodType = z.ZodObject<{
[Key in keyof Properties]: TFromProperty<Context, Properties[Key]>
}>
> = Result
type TFromString = z.ZodString
type TFromType<Context extends TProperties, Type extends TSchema> = (
Type extends TObject<infer Properties extends TProperties> ? TFromObject<Context, Properties> :
Type extends TRef<infer Ref extends string> ? TFromRef<Context, Ref> :
Type extends TString ? TFromString :
z.ZodNever
)
// ------------------------------------------------------------------
// Usage
// ------------------------------------------------------------------
type Input = TObject<{
x: TRef<'A'>,
y: TRef<'A'>,
z: TRef<'A'>
}>
type Output = TFromType<{ // type Output = z.ZodObject<{
A: TString // x: z.ZodString;
}, Input> // y: z.ZodString;
// z: z.ZodString;
// }, z.core.$strip>
🙁 Actual behavior
Expected similar behavior to TypeScript 6
🙂 Expected behavior
Expected similar behavior to TypeScript 6
Additional information about the issue
I note that by commenting the conditional TRef<T> arm on TFromType<T> will make the problem disappear. So the issue appears specific to how TypeScript 7 is resolving for the foreign type. Previous versions of the compiler did seem to collapse to the target type, where as TypeScript 7 seems to keep the type expansive.
🔎 Search Terms
Mapped Types, Satisfying Constraints, Recursive Type Mapping, TypeScript 7, RC
🕗 Version & Regression Information
Between
6.0.3and7.0.1-rcUnknown. However I recall things were working ok approximately 2 weeks ago. The update may be recent.
Tested
4.9.5through to6.0.3. Problem is specific to7.0.1-rc⏯ Playground Link
https://www.typescriptlang.org/play/?target=99&module=7&ts=4.9.5#code/JYWwDg9gTgLgBALzgMyhEcDkCIBNMBQBA9MXALSVXU2130ONMlkCSAdqgIYDOMUAVwDGMAVACmLCkxmy58ouIAekWHBgBPMOLgAVAMpCAFuJBc4AXjgBvdVvEAuOHyjB2AczgBfRSujxNbT0AeTAYYAh2LgAbAB5dezhlGHF2XB49QxMzS0zjUy4APlyEoIAyGywAPwgwiKjozCd+AR0fAmVVeDcUqGQuIR1dACVxZFjR5CSlFLSMlzd3YuTU9Lzs81sCODttJ0xJzAAaOG24CWQnSdOfTv84HvE+gaH9fkXp2bWDfJytncCjiwb1cHkwN18XV2QwACmhtLBgOIMlZRkJoLhYnDak9NABpcQaE4-DaFSH3R7PQYhABGACtxCIsfDcUiMis5npsQjwsjljNVhkSQUbGdAftgvTGTBCDswCzEcinNzWciCO1SNJ5NqddqpABZLhgMCLKS680WhgEQFwABaeFKOisCAAdOiJC79OhxI6iDbdAAxNAgSaxADCkRSM0+gq5Ct5PBO1w5awWHmKVgAFGdkwLOQBrQkQKYR9hRmBnHYAfj0QfQjvDkeSJ1L5YA2pMALpknY7Jyu+24ABy4gAbk8CABKa2JQPBlWwDSNsvJGOc3QLhPExIpoVZApHM4AdWAMCMjrXa0HF6sc-r9mX5e32kKh52J7PoXCkRil4y18SW8dzzb4v3qX8awHPAwJ-OIP3PexiiceDHUPDM4HgmCGj9Wc6xASUGSZVtV13OMcUVRM4E3Nk-zInk2TfOBNUNY1xFwPRElGdwJB4Hh6jgAAJJ5JB2Ugzk1YJ8ycHYADYXQABhdABmcSyADLhgGiJwAHYFJdABGcgoCEVTVLgABRKA0CgJwL0wWw2wJDQHnYOBCw0YsqPjNlO2VbzkUcwlO1osyQjqWD4n3MxihrQcsJieI8IbYiZhOaiAqc7tijgF1ctynNkQEaJ4FIgCgmdF04qlJlrErOBAuctw3KLKZ0p4Xza3neMlxSmA0v8ngGu7M4vDJdDRh4IqKxnII7xAEEPgqwcFo8HDZqSh9etojcBufHRSOFaLcmzHYLwOgjpViNxkCeLzyITba2pizr0Auoim1Su76L5OAHDOM6QKFUNrtu3Mvnmd50zgGs5tDXqkzGJD-uA8HMkhzwYbwlbPD+nYoOHMcJ2nM1LVJ0mpAAVR4Lh3EkTUyYZ801p0DgwAEeBbzemBYlqnYlFs0NMAAQUwV8zg0AWxliYXRcYhBJfGGWyVGmadGCdm2Y5l6QAbWxe01G11ZgTXcnxrmebOIXbOx3tbbtu3NT5-tKrwbGAG51ROVn2ey+2-YdsgdglxAXdwd26v9yP-cdxBneW9GPajpPo7ILwTldd1xBdAASBYwDJIA
💻 Code
The following code will fault on
7.0.1-rcThe issue relates to the
TFromObjectmapping where it's not possible to satisfy the left sideZodTypeconstraint. The issue is specific to resolving a foreignTRef<T>on a remoteContextobject.🙁 Actual behavior
Expected similar behavior to TypeScript 6
🙂 Expected behavior
Expected similar behavior to TypeScript 6
Additional information about the issue
I note that by commenting the conditional
TRef<T>arm onTFromType<T>will make the problem disappear. So the issue appears specific to how TypeScript 7 is resolving for the foreign type. Previous versions of the compiler did seem to collapse to the target type, where as TypeScript 7 seems to keep the type expansive.