Skip to content

Avoid resolving source prop type when the target is unknown/any #61660

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24057,6 +24057,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function isPropertySymbolTypeRelated(sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
const targetIsOptional = strictNullChecks && !!(getCheckFlags(targetProp) & CheckFlags.Partial);
const effectiveTarget = addOptionality(getNonMissingTypeOfSymbol(targetProp), /*isProperty*/ false, targetIsOptional);
// source could resolve to `any` and that's not related to `unknown` target under strict subtype relation
if (effectiveTarget.flags & (relation === strictSubtypeRelation ? TypeFlags.Any : TypeFlags.AnyOrUnknown)) {
return Ternary.True;
}
const effectiveSource = getTypeOfSourceProperty(sourceProp);
return isRelatedTo(effectiveSource, effectiveTarget, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/multiline.types
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

=== Performance Stats ===
Type Count: 2,500
Instantiation count: 2,500
Instantiation count: 1,000

=== a.ts ===
export const texts: string[] = [];
Expand Down
142 changes: 142 additions & 0 deletions tests/baselines/reference/noCircularitySelfReferentialGetter1.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//// [tests/cases/compiler/noCircularitySelfReferentialGetter1.ts] ////

=== noCircularitySelfReferentialGetter1.ts ===
// https://github.com/microsoft/TypeScript/issues/61659

interface ZodType {
>ZodType : Symbol(ZodType, Decl(noCircularitySelfReferentialGetter1.ts, 0, 0))

optional: "true" | "false";
>optional : Symbol(ZodType.optional, Decl(noCircularitySelfReferentialGetter1.ts, 2, 19))

output: any;
>output : Symbol(ZodType.output, Decl(noCircularitySelfReferentialGetter1.ts, 3, 29))
}

interface ZodString extends ZodType {
>ZodString : Symbol(ZodString, Decl(noCircularitySelfReferentialGetter1.ts, 5, 1))
>ZodType : Symbol(ZodType, Decl(noCircularitySelfReferentialGetter1.ts, 0, 0))

optional: "false";
>optional : Symbol(ZodString.optional, Decl(noCircularitySelfReferentialGetter1.ts, 7, 37))

output: string;
>output : Symbol(ZodString.output, Decl(noCircularitySelfReferentialGetter1.ts, 8, 20))
}

type ZodShape = Record<string, any>;
>ZodShape : Symbol(ZodShape, Decl(noCircularitySelfReferentialGetter1.ts, 10, 1))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))

type Prettify<T> = { [K in keyof T]: T[K] } & {};
>Prettify : Symbol(Prettify, Decl(noCircularitySelfReferentialGetter1.ts, 12, 36))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 13, 14))
>K : Symbol(K, Decl(noCircularitySelfReferentialGetter1.ts, 13, 22))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 13, 14))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 13, 14))
>K : Symbol(K, Decl(noCircularitySelfReferentialGetter1.ts, 13, 22))

type InferObjectType<Shape extends ZodShape> = Prettify<
>InferObjectType : Symbol(InferObjectType, Decl(noCircularitySelfReferentialGetter1.ts, 13, 49))
>Shape : Symbol(Shape, Decl(noCircularitySelfReferentialGetter1.ts, 14, 21))
>ZodShape : Symbol(ZodShape, Decl(noCircularitySelfReferentialGetter1.ts, 10, 1))
>Prettify : Symbol(Prettify, Decl(noCircularitySelfReferentialGetter1.ts, 12, 36))
{
[k in keyof Shape as Shape[k] extends { optional: "true" }
>k : Symbol(k, Decl(noCircularitySelfReferentialGetter1.ts, 16, 5))
>Shape : Symbol(Shape, Decl(noCircularitySelfReferentialGetter1.ts, 14, 21))
>Shape : Symbol(Shape, Decl(noCircularitySelfReferentialGetter1.ts, 14, 21))
>k : Symbol(k, Decl(noCircularitySelfReferentialGetter1.ts, 16, 5))
>optional : Symbol(optional, Decl(noCircularitySelfReferentialGetter1.ts, 16, 43))

? k
>k : Symbol(k, Decl(noCircularitySelfReferentialGetter1.ts, 16, 5))

: never]?: Shape[k]["output"];
>Shape : Symbol(Shape, Decl(noCircularitySelfReferentialGetter1.ts, 14, 21))
>k : Symbol(k, Decl(noCircularitySelfReferentialGetter1.ts, 16, 5))

} & {
[k in keyof Shape as Shape[k] extends { optional: "true" }
>k : Symbol(k, Decl(noCircularitySelfReferentialGetter1.ts, 20, 5))
>Shape : Symbol(Shape, Decl(noCircularitySelfReferentialGetter1.ts, 14, 21))
>Shape : Symbol(Shape, Decl(noCircularitySelfReferentialGetter1.ts, 14, 21))
>k : Symbol(k, Decl(noCircularitySelfReferentialGetter1.ts, 20, 5))
>optional : Symbol(optional, Decl(noCircularitySelfReferentialGetter1.ts, 20, 43))

? never
: k]: Shape[k]["output"];
>k : Symbol(k, Decl(noCircularitySelfReferentialGetter1.ts, 20, 5))
>Shape : Symbol(Shape, Decl(noCircularitySelfReferentialGetter1.ts, 14, 21))
>k : Symbol(k, Decl(noCircularitySelfReferentialGetter1.ts, 20, 5))
}
>;
interface ZodObject<T extends ZodShape> extends ZodType {
>ZodObject : Symbol(ZodObject, Decl(noCircularitySelfReferentialGetter1.ts, 24, 2))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 25, 20))
>ZodShape : Symbol(ZodShape, Decl(noCircularitySelfReferentialGetter1.ts, 10, 1))
>ZodType : Symbol(ZodType, Decl(noCircularitySelfReferentialGetter1.ts, 0, 0))

optional: "false";
>optional : Symbol(ZodObject.optional, Decl(noCircularitySelfReferentialGetter1.ts, 25, 57))

output: InferObjectType<T>;
>output : Symbol(ZodObject.output, Decl(noCircularitySelfReferentialGetter1.ts, 26, 20))
>InferObjectType : Symbol(InferObjectType, Decl(noCircularitySelfReferentialGetter1.ts, 13, 49))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 25, 20))
}

interface ZodOptional<T extends ZodType> extends ZodType {
>ZodOptional : Symbol(ZodOptional, Decl(noCircularitySelfReferentialGetter1.ts, 28, 1))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 30, 22))
>ZodType : Symbol(ZodType, Decl(noCircularitySelfReferentialGetter1.ts, 0, 0))
>ZodType : Symbol(ZodType, Decl(noCircularitySelfReferentialGetter1.ts, 0, 0))

optional: "true";
>optional : Symbol(ZodOptional.optional, Decl(noCircularitySelfReferentialGetter1.ts, 30, 58))

output: T["output"] | undefined;
>output : Symbol(ZodOptional.output, Decl(noCircularitySelfReferentialGetter1.ts, 31, 19))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 30, 22))
}

declare function object<T extends ZodShape>(shape: T): ZodObject<T>;
>object : Symbol(object, Decl(noCircularitySelfReferentialGetter1.ts, 33, 1))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 35, 24))
>ZodShape : Symbol(ZodShape, Decl(noCircularitySelfReferentialGetter1.ts, 10, 1))
>shape : Symbol(shape, Decl(noCircularitySelfReferentialGetter1.ts, 35, 44))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 35, 24))
>ZodObject : Symbol(ZodObject, Decl(noCircularitySelfReferentialGetter1.ts, 24, 2))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 35, 24))

declare function string(): ZodString;
>string : Symbol(string, Decl(noCircularitySelfReferentialGetter1.ts, 35, 68))
>ZodString : Symbol(ZodString, Decl(noCircularitySelfReferentialGetter1.ts, 5, 1))

declare function optional<T extends ZodType>(schema: T): ZodOptional<T>;
>optional : Symbol(optional, Decl(noCircularitySelfReferentialGetter1.ts, 36, 37))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 37, 26))
>ZodType : Symbol(ZodType, Decl(noCircularitySelfReferentialGetter1.ts, 0, 0))
>schema : Symbol(schema, Decl(noCircularitySelfReferentialGetter1.ts, 37, 45))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 37, 26))
>ZodOptional : Symbol(ZodOptional, Decl(noCircularitySelfReferentialGetter1.ts, 28, 1))
>T : Symbol(T, Decl(noCircularitySelfReferentialGetter1.ts, 37, 26))

const Category = object({
>Category : Symbol(Category, Decl(noCircularitySelfReferentialGetter1.ts, 39, 5))
>object : Symbol(object, Decl(noCircularitySelfReferentialGetter1.ts, 33, 1))

name: string(),
>name : Symbol(name, Decl(noCircularitySelfReferentialGetter1.ts, 39, 25))
>string : Symbol(string, Decl(noCircularitySelfReferentialGetter1.ts, 35, 68))

get parent() {
>parent : Symbol(parent, Decl(noCircularitySelfReferentialGetter1.ts, 40, 17))

return optional(Category);
>optional : Symbol(optional, Decl(noCircularitySelfReferentialGetter1.ts, 36, 37))
>Category : Symbol(Category, Decl(noCircularitySelfReferentialGetter1.ts, 39, 5))

},
});

120 changes: 120 additions & 0 deletions tests/baselines/reference/noCircularitySelfReferentialGetter1.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//// [tests/cases/compiler/noCircularitySelfReferentialGetter1.ts] ////

=== noCircularitySelfReferentialGetter1.ts ===
// https://github.com/microsoft/TypeScript/issues/61659

interface ZodType {
optional: "true" | "false";
>optional : "true" | "false"
> : ^^^^^^^^^^^^^^^^

output: any;
>output : any
}

interface ZodString extends ZodType {
optional: "false";
>optional : "false"
> : ^^^^^^^

output: string;
>output : string
> : ^^^^^^
}

type ZodShape = Record<string, any>;
>ZodShape : ZodShape
> : ^^^^^^^^

type Prettify<T> = { [K in keyof T]: T[K] } & {};
>Prettify : { [K in keyof T]: T[K]; }
> : ^^^ ^^^^^^^^^^^^^^^^^^^^^

type InferObjectType<Shape extends ZodShape> = Prettify<
>InferObjectType : { [k in keyof Shape as Shape[k] extends { optional: "true"; } ? k : never]?: Shape[k]["output"] | undefined; } & { [k_1 in keyof Shape as Shape[k_1] extends { optional: "true"; } ? never : k_1]: Shape[k_1]["output"]; } extends infer T ? { [K in keyof T]: ({ [k in keyof Shape as Shape[k] extends { optional: "true"; } ? k : never]?: Shape[k]["output"] | undefined; } & { [k_1 in keyof Shape as Shape[k_1] extends { optional: "true"; } ? never : k_1]: Shape[k_1]["output"]; })[K]; } : never
> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
[k in keyof Shape as Shape[k] extends { optional: "true" }
>optional : "true"
> : ^^^^^^

? k
: never]?: Shape[k]["output"];
} & {
[k in keyof Shape as Shape[k] extends { optional: "true" }
>optional : "true"
> : ^^^^^^

? never
: k]: Shape[k]["output"];
}
>;
interface ZodObject<T extends ZodShape> extends ZodType {
optional: "false";
>optional : "false"
> : ^^^^^^^

output: InferObjectType<T>;
>output : { [k in keyof T as T[k] extends { optional: "true"; } ? k : never]?: T[k]["output"] | undefined; } & { [k_1 in keyof T as T[k_1] extends { optional: "true"; } ? never : k_1]: T[k_1]["output"]; } extends infer T_1 ? { [K in keyof T_1]: ({ [k in keyof T as T[k] extends { optional: "true"; } ? k : never]?: T[k]["output"] | undefined; } & { [k_1 in keyof T as T[k_1] extends { optional: "true"; } ? never : k_1]: T[k_1]["output"]; })[K]; } : never
> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

interface ZodOptional<T extends ZodType> extends ZodType {
optional: "true";
>optional : "true"
> : ^^^^^^

output: T["output"] | undefined;
>output : T["output"] | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^
}

declare function object<T extends ZodShape>(shape: T): ZodObject<T>;
>object : <T extends ZodShape>(shape: T) => ZodObject<T>
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>shape : T
> : ^

declare function string(): ZodString;
>string : () => ZodString
> : ^^^^^^

declare function optional<T extends ZodType>(schema: T): ZodOptional<T>;
>optional : <T extends ZodType>(schema: T) => ZodOptional<T>
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>schema : T
> : ^

const Category = object({
>Category : ZodObject<{ name: ZodString; readonly parent: ZodOptional<ZodObject<any>>; }>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>object({ name: string(), get parent() { return optional(Category); },}) : ZodObject<{ name: ZodString; readonly parent: ZodOptional<ZodObject<any>>; }>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>object : <T extends ZodShape>(shape: T) => ZodObject<T>
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>{ name: string(), get parent() { return optional(Category); },} : { name: ZodString; readonly parent: ZodOptional<ZodObject<{ name: ZodString; readonly parent: ZodOptional<ZodObject<any>>; }>>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

name: string(),
>name : ZodString
> : ^^^^^^^^^
>string() : ZodString
> : ^^^^^^^^^
>string : () => ZodString
> : ^^^^^^

get parent() {
>parent : ZodOptional<ZodObject<{ name: ZodString; readonly parent: ZodOptional<ZodObject<any>>; }>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

return optional(Category);
>optional(Category) : ZodOptional<ZodObject<{ name: ZodString; readonly parent: ZodOptional<ZodObject<any>>; }>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>optional : <T extends ZodType>(schema: T) => ZodOptional<T>
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>Category : ZodObject<{ name: ZodString; readonly parent: ZodOptional<ZodObject<any>>; }>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

},
});

Loading