【问题标题】:TypeScript Optimization Help - "Type instantiation is excessively deep and possibly infinite.(2589)"TypeScript 优化帮助 - “类型实例化过深并且可能无限。(2589)”
【发布时间】:2022-01-05 09:29:49
【问题描述】:

我有一些 TypeScript 代码,我试图从元素属性的完整对象中提取 data- 属性。但是,我遇到了一个错误,“类型实例化过深并且可能是无限的。(2589)”。

认为我的代码可能会被优化来解决这个问题——我可能过于复杂了——所以我很感激专家的眼睛看看它是否可以帮助,或者如果我是什么努力去做太难了。

这是TS Repl 的链接,我已将以下代码包含在内:

type AnyArray = any[];
type AnyArrayWithItems = [any, ...any];
type AnyFunction<Arguments extends any[] = any[]> = (...args: Arguments) => any;

// The type of the first item in an array.
// Input: `[1, 2, 3]`
// Output: `1`
type Head<SomeArray extends AnyArray> = SomeArray extends AnyArrayWithItems
    ? SomeArray[0]
    : never;

// The type of an array after removing the first element.
// Input: `[1, 2, 3]`
// Output: `[2, 3]`
type Tail<SomeArray extends AnyArray> = AnyFunction<SomeArray> extends (
    _: any,
    ...args: infer Remainder
) => any
    ? Remainder
    : never;

const DATA_KEY_PREFIX = "data-" as const;

type DataKey = `${typeof DATA_KEY_PREFIX}${string}`;

type PrependIfDataKey<
    Key extends string | number | symbol,
> = Key extends DataKey ? [Key] : [];

type DataKeys<
    Keys extends (string | number | symbol)[],
> = Keys['length'] extends 0 ? [] : [
    ...PrependIfDataKey<Head<Keys>>,
    ...DataKeys<Tail<Keys>>
];

type DataProps<Props extends Record<string, unknown>> = Pick<
    Props,
    DataKeys<(keyof Props)[]>
>;

function getDataAttributes<Props extends Record<string, unknown>>(
    props: Props,
): DataProps<Props> {
    return Object.keys(props)
        .filter((propName): propName is DataKey =>
            propName.startsWith(DATA_KEY_PREFIX),
        )
        .reduce(
            (dataProps, propName) => ({ ...dataProps, [propName]: props[propName] }),
            {} as DataProps<Props>,
        );
}


const test = { href: "#", onClick: () => null, 'data-foo': 'bar' };
const attrs = getDataAttributes(test);

【问题讨论】:

    标签: javascript typescript recursion typescript-generics


    【解决方案1】:

    与其试图梳理你的递归类型,看看是否有办法让编译器更快乐,我认为最好退后一步,直接通过key remappingDataProps

    type DataProps<T> = { [K in keyof T as Extract<K, DataKey>]: T[K] };
    

    如果您将密钥重新映射到 never,则密钥重新映射允许您省略属性。所以我使用the Extract&lt;T, U&gt; utility type 只保留可分配给DataKey 的键K

    这在您的示例代码中可以正常工作:

    const test = { href: "#", onClick: () => null, 'data-foo': 'bar' };
    const attrs = getDataAttributes(test);
    
    type Attrs = typeof attrs;
    /* type Attrs = {
        "data-foo": string;
    } */
    

    Playground link to code

    【讨论】:

    • 难以置信,谢谢!我知道我一定错过了什么。关于Extract!
    猜你喜欢
    • 2021-06-25
    • 2020-02-10
    • 2023-02-22
    • 1970-01-01
    • 2020-01-08
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多