Steps to reproduce
types.ts
// Utility types from type-fest/remeda that create deeply nested conditional chains
type IsNever<T> = [T] extends [never] ? true : false;
type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false;
type If<T extends boolean, Then, Else> = IsNever<T> extends true ? Else : T extends true ? Then : Else;
type IfNotAnyOrNever<T, Then, IfAny = any, IfNever = never> = If<IsAny<T>, IfAny, If<IsNever<T>, IfNever, Then>>;
type Or<A extends boolean, B extends boolean> = If<IsNever<A>, false, A> extends true ? true : If<IsNever<B>, false, B> extends true ? true : false;
type CollapseLiterals<T> = {} extends T ? T : T extends infer U & {} ? U : T;
type Simplify<T> = { [K in keyof T]: T[K] } & {};
type UnionToIntersection<U> = (
U extends unknown ? (x: U) => void : never
) extends (x: infer I) => void ? I & U : never;
type KeysOfUnion<T> = keyof UnionToIntersection<
T extends unknown ? Record<keyof T, never> : never
>;
// Tag branding types — these create enough conditional depth to prevent type simplification
declare const tag: unique symbol;
type TagContainer<Token> = { readonly [tag]: Token };
type Tag<Token extends PropertyKey, Meta> = TagContainer<{ [K in Token]: Meta }>;
type Tagged<T, Name extends PropertyKey, Meta = never> = T & Tag<Name, Meta>;
type RemoveAllTags<T> = T extends Tag<PropertyKey, any>
? { [K in keyof T[typeof tag]]: T extends Tagged<infer U, K, T[typeof tag][K]> ? RemoveAllTags<U> : never }[keyof T[typeof tag]]
: T;
// String literal detection with tag-aware unwrapping
type IsStringLiteral<S> = IfNotAnyOrNever<S,
(CollapseLiterals<S extends TagContainer<any> ? RemoveAllTags<S> : S>) extends infer C extends string
? {} extends Record<C, never> ? false : true
: false,
false, false>;
// Recursive string splitting
type SplitHelper<S extends string, D extends string, Acc extends string[] = []> =
S extends string ? D extends string ?
Or<false, IsStringLiteral<S> extends true ? IsStringLiteral<D> : false> extends true
? S extends `${infer Head}${D}${infer Tail}` ? SplitHelper<Tail, D, [...Acc, Head]>
: D extends '' ? S extends '' ? Acc : [...Acc, S] : [...Acc, S]
: string[]
: never : never;
// Bounded key detection
type IsBoundedString<T> = T extends string ? IsStringLiteral<T> extends true
? SplitHelper<T, "">[number] extends infer U
? [`${number}`] extends [U] ? false : [string] extends [U] ? false : true
: false : false : false;
type IsBounded<T> = (T extends unknown ? Or<IsBoundedString<T>, false> : never) extends true ? true : false;
// The pick return type that triggers circular inference
type PickFromArray<T, Keys extends readonly KeysOfUnion<T>[]> =
T extends unknown ? Keys extends unknown
? Simplify<IsBounded<KeysOfUnion<T>> extends true
? Pick<T, Extract<Keys[number], keyof T>>
: Pick<T, Extract<Keys[number], keyof T>>>
: never : never;
export declare function pick<T extends object, const Keys extends readonly KeysOfUnion<T>[]>(
data: T, keys: Keys
): PickFromArray<T, Keys>;
repro.ts
import { pick } from "./types";
export class MyClass {
constructor(public readonly field: number) {}
getIdentity() {
return pick(this, ["field"]);
}
}
Run tsc -d / tsgo -d
Behavior with typescript@6.0
epro.ts:5:3 - error TS2527: The inferred type of 'getIdentity' references an inaccessible 'unique symbol' type. A type annotation is necessary.
5 getIdentity() {
~~~~~~~~~~~
repro.ts:5:3 - error TS4053: Return type of public method from exported class has or is using name 'tag' from external module "D:/Throwaway/63207_/types" but cannot be named.
5 getIdentity() {
~~~~~~~~~~~
repro.ts:5:3 - error TS7056: The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.
5 getIdentity() {
~~~~~~~~~~~
Found 3 errors in the same file, starting at: repro.ts:5
Behavior with tsgo
Same errors, but emits a 2.4 MB repro.d.ts file
Steps to reproduce
types.ts
repro.ts
Run
tsc -d/tsgo -dBehavior with
typescript@6.0Behavior with
tsgoSame errors, but emits a 2.4 MB repro.d.ts file