Skip to content

Instantly share code, notes, and snippets.

@zirkelc
Created January 6, 2024 15:24
Show Gist options
  • Save zirkelc/1ef0054206e7485f1a39d09c6630cf4e to your computer and use it in GitHub Desktop.
Save zirkelc/1ef0054206e7485f1a39d09c6630cf4e to your computer and use it in GitHub Desktop.
Infer type of unused generic parameters
/* object types */
// generic parameters T1, T2, T3 are not used in the actual type definition
type GenericObject<T1 extends any, T2 extends any, T3 extends any> = {};
const obj: GenericObject<{ a: string }, number[], boolean> = {};
type InferT1FromGenricObject<TObj> = TObj extends GenericObject<infer T1, any, any> ? T1 : never;
type InferT2FromGenricObject<TObj> = TObj extends GenericObject<any, infer T2, any> ? T2 : never;
type InferT3FromGenricObject<TObj> = TObj extends GenericObject<any, any, infer T3> ? T3 : never;
// nevertheless, you can infer the types of the generic parameters from the object
type O1 = InferT1FromGenricObject<typeof obj>;
// ^^
// type O1 = { a: string; }
type O2 = InferT2FromGenricObject<typeof obj>;
// ^^
// type O2 = number[]
type O3 = InferT3FromGenricObject<typeof obj>;
// ^^
// type O3 = boolean
/* array types */
// generic parameters T1, T2, T3 are not used in the actual type definition
type GenericArray<T1 extends any, T2 extends any, T3 extends any> = [];
const array: GenericArray<{ a: string }, number[], boolean> = [];
type InferT1FromGenricArray<TArray> = TArray extends GenericArray<infer T1, any, any> ? T1 : never;
type InferT2FromGenricArray<TArray> = TArray extends GenericArray<any, infer T2, any> ? T2 : never;
type InferT3FromGenricArray<TArray> = TArray extends GenericArray<any, any, infer T3> ? T3 : never;
// this doesn't seem to work with array types
type A1 = InferT1FromGenricArray<typeof array>;
// ^^
// type A1 = unknown
type A2 = InferT2FromGenricArray<typeof array>;
// ^^
// type A2 = unknown
type A3 = InferT3FromGenricArray<typeof array>;
// ^^
// type A3 = unknown
/* primitive types */
// generic parameters T1, T2, T3 are not used in the actual type definition
type GenericString<T1 extends any, T2 extends any, T3 extends any> = string;
const str: GenericString<{ a: string }, number[], boolean> = '';
type InferT1FromGenricString<TString> = TString extends GenericString<infer T1, any, any> ? T1 : never;
type InferT2FromGenricString<TString> = TString extends GenericString<any, infer T2, any> ? T2 : never;
type InferT3FromGenricString<TString> = TString extends GenericString<any, any, infer T3> ? T3 : never;
// or primitive types
type S1 = InferT1FromGenricString<typeof str>;
// ^^
// type S1 = unknown
type S2 = InferT2FromGenricString<typeof str>;
// ^^
// type S2 = unknown
type S3 = InferT3FromGenricString<typeof str>;
// ^^
// type S3 = unknown
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment