Repository navigation
Assignment to an any-parameterised generic rejected by tsgo, accepted by tsc 6.0.3 #63881
Description
Steps to reproduce
In an empty directory:
npm init -y
npm install typescript@6.0.3 yup@1.4.0repro.ts:
import { AnyObjectSchema, ObjectSchema, number, object, string } from "yup";
interface FormData {
name: string;
amount: number;
}
const schema: ObjectSchema<FormData> = object({
name: string().required(),
amount: number().required(),
});
const widened: AnyObjectSchema = schema;
export { widened };npx tsc --noEmit --strict --target es2020 repro.ts
npx tsgo --noEmit --strict --target es2020 repro.tsAnyObjectSchema is yup's own alias for ObjectSchema<any, any, any, any>.
Reproduces with and without --skipLibCheck, and also when yup's declarations are copied into a local .d.ts.
Behavior with typescript@6.0
Compiles clean, exit code 0.
Also clean with --stableTypeOrdering, so this is not explained by deterministic type ordering:
tsc --noEmit --strict --target es2020 repro.ts # exit 0
tsc --noEmit --strict --target es2020 --stableTypeOrdering repro.ts # exit 0
Behavior with tsgo
repro.ts(13,7): error TS2322: Type 'ObjectSchema<FormData, AnyObject, any, "">' is not assignable to type 'AnyObjectSchema'.
The types returned by 'optional().concat' are incompatible between these types.
Type '{ <IIn extends Maybe<AnyObject>, IC, ID, IF extends Flags>(schema: ObjectSchema<IIn, IC, ID, IF>): ObjectSchema<ConcatObjectTypes<FormData | undefined, IIn>, AnyObject & IC, ..., "" | IF>; (schema: ObjectSchema<...>): ObjectSchema<...>; }' is not assignable to type '{ <IIn extends Maybe<AnyObject>, IC, ID, IF extends Flags>(schema: ObjectSchema<IIn, IC, ID, IF>): ObjectSchema<ConcatObjectTypes<any, IIn>, any, Extract<IF, "d"> extends never ? ID | ... : ID, any>; (schema: ObjectSchema<...>): ObjectSchema<...>; }'.
Types of parameters 'schema' and 'schema' are incompatible.
Type 'ObjectSchema<any, any, any, any>' is not assignable to type 'ObjectSchema<FormData | undefined, AnyObject, any, "">'.
The types returned by 'default(...).fields' are incompatible between these types.
Type 'Shape<any, any>' is missing the following properties from type 'Shape<FormData, AnyObject>': name, amount
Exit code 1. Confirmed failing on 7.0.2, 7.1.0-dev.20260807.1 and 7.1.0-dev.20260810.1.
Analysis
The last line looks like the crux. The relevant yup declarations are:
type Shape<T extends Maybe<AnyObject>, C = any> = {
[field in keyof T]-?: ISchema<T[field], C> | Reference;
};
declare class ObjectSchema<TIn extends Maybe<AnyObject>, TContext = AnyObject, ...> {
fields: Shape<NonNullable<TIn>, TContext>;
concat<IIn extends Maybe<AnyObject>, IC, ID, IF extends Flags>(
schema: ObjectSchema<IIn, IC, ID, IF>
): ObjectSchema<...>;
}Shape<any, any> is a mapped type over keyof any, so it should be compatible with any instantiation — but it is reported as missing properties. any appears to stop absorbing the structural difference once the check recurses into the generic concat parameter position.
Narrowing
It only reproduces when the schema type is explicitly annotated. Holding the construction identical and changing only the annotation flips it:
// fails on tsgo
const annotated: ObjectSchema<FormData> = object({
name: string().required(),
amount: number().required(),
});
const a: AnyObjectSchema = annotated; // TS2322 on tsgo, fine on tsc 6
// passes on tsgo -- identical construction, type left inferred
const checked = object({
name: string().required(),
amount: number().required(),
}) satisfies ObjectSchema<FormData>;
const b: AnyObjectSchema = checked; // fine on bothsatisfies performs the same assignability check, so the difference is purely whether the declared instantiation is what flows into the comparison. Same result via a factory returning object().shape({ ... }), annotated ): ObjectSchema<FormData> => versus return schema satisfies ObjectSchema<FormData> — so it is the annotation, not the construction form.
We hit this because two otherwise identical call sites in our codebase behaved differently: the one whose schema factory declared ): ObjectSchema<T> => failed, the one that let the return type infer did not.
I could not reduce this to a dependency-free case. Six hand-written models of the shape (mapped type with -?, Shape<NonNullable<TIn>>, values depending on T[K], interface/declare class merging, a this-typed concat overload, four type parameters with a conditional return type) all compiled clean on both compilers, so the trigger appears subtler than the error text suggests. A declaration-level delta-debugger over yup's own index.d.ts only got 893 → 776 lines without --skipLibCheck.
Switching those factories to satisfies is what we shipped, so we are not blocked — but it looks like a genuine divergence worth fixing.
Activity
mrazauskas commentedon Aug 10, 2026
Could you double-check, please? Something might be mixed up here, because the reproduction steps in the OP are identical to microsoft/typescript-go#4862
richardquaite commentedon Aug 10, 2026
Sorry about that, Please see updated issue
ahejlsberg commentedon Aug 14, 2026
This is working as intended and is an indirect effect of microsoft/typescript-go#3445. With microsoft/typescript-go#3445 the checker more deeply analyses relationships between different instantiations of
ObjectSchema. This in turn reveals thatShape<any, any>is not assignable toShape<FormData, AnyObject>which ultimately is because the type{ [x: keyof any]: any }(which reduces to{ [x: string]: any }) isn't assignable to a type that has concrete properties. In TS6 (i.e. before microsoft/typescript-go#3445), analysis ofObjectSchemainstantiation relationships would terminate before the checker got deep enough to reveal the incompatibility.typescript-automation commentedon Aug 23, 2026
This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.