Skip to content
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

Type inference performance issue #60772

Open
1 task done
gumartinezedicom opened this issue Dec 16, 2024 · 0 comments
Open
1 task done

Type inference performance issue #60772

gumartinezedicom opened this issue Dec 16, 2024 · 0 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@gumartinezedicom
Copy link

Acknowledgement

  • I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion.

Comment

I have been trying to use type inference for a specific case.

interface Model {
    field1: Date;
    field2: number;
}

interface Column<T, K extends keyof T = keyof T> {
    field: K;
    transformation?: (value: T[K], data: Model) => string;
}

const columns: Column<Model>[] =  [
    {
        field: 'field1',
        transformation: (value) => value.getTime()
    }
];

In 'transformation,' I would like 'value' to be of type Date instead of being number | Date.

To achieve this, I created two helper types to get the union of possible 'field' types and to correctly infer the type from 'field' in the callback.

interface Column<
    T,
    K extends NestedKeyOf<T>,
    V extends NestedValueOf<T, K>,
> {
    field: K & string;
    transformation?: (value: V, data: Model) => string;
}

for NestedKeyOf

type NestedKeyOf<Type> = Type extends string | number
  ? never
  : {
      [Key in TraversableKeys<Type>]: NestedSingleKeyOf<Type, Key>;
    }[TraversableKeys<Type>];

type TraversableKeys<Type> = Exclude<keyof Type & (string | number), 'prototype'>;

type NestedSingleKeyOf<Type, Key extends keyof Type> = Key extends string
  ? IsArray<
      Type[Key],
      Key | `${Key}.${number}`,
      IsComplexObject<Type[Key], Key | `${Key}.${NestedKeyOf<Type[Key]>}`, Key>
    >
  : never;

type IsArray<O, T, F> = O extends Array<unknown> ? T : F;

type IsComplexObject<O, T, F> = O extends Date | Array<unknown> | Blob
  ? F
  : IsObject<O, T, F>;

type IsObject<O, T, F> = O extends object ? T : F;

for NestedValueOf

type NestedValueOf<Type, Key extends string> = Key extends `${infer Head}.${infer Tail}`
  ? Head extends keyof Type
    ? IsNumberFromString<
        Tail,
        IsArrayValue<Type[Head], NestedValueOf<Type[Head], Tail>>,
        NestedValueOf<Type[Head], Tail>
      >
    : never
  : IsKeyOfType<Type, Key>;

type IsArrayValue<O, F> = O extends Array<infer U> ? U : F;

type IsNumberFromString<O, T, F> = O extends `${number}` ? T : F;

type IsKeyOfType<Type, Key> = Key extends keyof Type ? Type[Key] : never;

This way, the type of 'value' is correctly inferred in the callback. I can even access different levels of nesting using dots, such as 'field1.field1-2.field1-2-1,' or even array positions, inferring the correct type like 'field1.6'.

From this point, my problem is that in cases with multiple levels of nesting (3 or more) and types with many properties (20–30 or more), it takes a long time to compute the corresponding type. Is there any way to optimize the typing or handle it differently?

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Dec 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

2 participants