打字稿优化帮助 - "Type instantiation is excessively deep and possibly infinite.(2589)"



我有一些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);

与其试图区分递归类型,看看是否有办法让编译器更快乐,我认为最好退一步,通过键重映射直接编写DataProps

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

如果将密钥重新映射到never,则可以通过密钥重新映射省略特性。因此,我使用Extract<T, U>实用程序类型只保留可分配给DataKey的密钥K

这在您的示例代码上起到了预期的作用:

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

游乐场链接到代码