TypeScript 优化帮助 - “类型实例化过深且可能是无限的。(2589)”

Rub*_*Jr. 5 javascript recursion typescript typescript-generics

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

\n

我认为我的代码可能可以优化以修复此问题\xe2\x80\x94我可能会使它过于复杂\xe2\x80\x94所以我希望有专家的眼光来看看它是否可以提供帮助,或者我是否可以尝试去做太难了。

\n

这是TS Repl的链接,我添加了以下代码:

\n
type AnyArray = any[];\ntype AnyArrayWithItems = [any, ...any];\ntype AnyFunction<Arguments extends any[] = any[]> = (...args: Arguments) => any;\n\n// The type of the first item in an array.\n// Input: `[1, 2, 3]`\n// Output: `1`\ntype Head<SomeArray extends AnyArray> = SomeArray extends AnyArrayWithItems\n    ? SomeArray[0]\n    : never;\n\n// The type of an array after removing the first element.\n// Input: `[1, 2, 3]`\n// Output: `[2, 3]`\ntype Tail<SomeArray extends AnyArray> = AnyFunction<SomeArray> extends (\n    _: any,\n    ...args: infer Remainder\n) => any\n    ? Remainder\n    : never;\n\nconst DATA_KEY_PREFIX = "data-" as const;\n\ntype DataKey = `${typeof DATA_KEY_PREFIX}${string}`;\n\ntype PrependIfDataKey<\n    Key extends string | number | symbol,\n> = Key extends DataKey ? [Key] : [];\n\ntype DataKeys<\n    Keys extends (string | number | symbol)[],\n> = Keys[\'length\'] extends 0 ? [] : [\n    ...PrependIfDataKey<Head<Keys>>,\n    ...DataKeys<Tail<Keys>>\n];\n\ntype DataProps<Props extends Record<string, unknown>> = Pick<\n    Props,\n    DataKeys<(keyof Props)[]>\n>;\n\nfunction getDataAttributes<Props extends Record<string, unknown>>(\n    props: Props,\n): DataProps<Props> {\n    return Object.keys(props)\n        .filter((propName): propName is DataKey =>\n            propName.startsWith(DATA_KEY_PREFIX),\n        )\n        .reduce(\n            (dataProps, propName) => ({ ...dataProps, [propName]: props[propName] }),\n            {} as DataProps<Props>,\n        );\n}\n\n\nconst test = { href: "#", onClick: () => null, \'data-foo\': \'bar\' };\nconst attrs = getDataAttributes(test);\n
Run Code Online (Sandbox Code Playgroud)\n

jca*_*alz 4

DataProps我认为最好退后一步,直接通过键重新映射来编写,而不是试图梳理递归类型以查看是否有办法让编译器更满意:

type DataProps<T> = { [K in keyof T as Extract<K, DataKey>]: T[K] };
Run Code Online (Sandbox Code Playgroud)

如果将键重新映射到 ,则键重新映射允许您省略属性never。因此,我使用实用程序类型仅Extract<T, U>保留K可分配给 的键DataKey。

这可以按照您的示例代码的要求工作:

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

type Attrs = typeof attrs;
/* type Attrs = {
    "data-foo": string;
} */
Run Code Online (Sandbox Code Playgroud)

Playground 代码链接