如何编写从另一种类型的键中剥离前缀的 TypeScript 类型

How to write a TypeScript type that strips a prefix from the keys of another type

我正在尝试编写一种可以从另一种类型的键中去除给定前缀的类型。

我试过以下代码:

type StripPrefix<
  TPrefix extends string,
  T extends `${TPrefix}.${string}`,
> = T extends `${TPrefix}.${infer R}` ? R : never;

type MapKeysStripPrefix<T, TPrefix extends string> = {
  [K in StripPrefix<TPrefix, keyof T & `${TPrefix}.${string}`>]: Pick<
    T,
    keyof T & `${TPrefix}.${string}`
  >[`${TPrefix}.${K}`];
};

type test = {
  'test.blah': 1;
  'test.foo': 2;
  'bar.baz': 3;
};

type result = MapKeysStripPrefix<test, 'test'>;

但是我得到一个错误:

Type '`${TPrefix}.${K}`' cannot be used to index type 'Pick<T, keyof T & `${TPrefix}.${string}`>'

我意识到这可能是不可能的。

关键是要保留中间类型参数K,这样您就可以用它来索引记录的值。

type StripPrefix<
  TPrefix extends string,
  T extends `${TPrefix}.${string}`,
> = T extends `${TPrefix}.${infer R}` ? R : never;

type MapKeysStripPrefix<T, P extends string> = {
  [K in keyof T & `${P}.${string}`]: { [N in StripPrefix<P, K>]: T[K] }
}[keyof T & `${P}.${string}`]

type test = {
  'test.blah': 1;
  'test.foo': 2;
  'bar.baz': 3;
  'kk': 5
};

type R = MapKeysStripPrefix<test, 'test'>;

let rec: R = {blah: 1, foo: 2}

Playground

如果你利用 key remapping via as 那么这就容易多了:

type StripPrefix<
  TPrefix extends string,
  T extends string, // changed this constraint to string
> = T extends `${TPrefix}.${infer R}` ? R : never;

type MapKeysStripPrefix<T, TPrefix extends string> = {
  [K in keyof T & string as StripPrefix<TPrefix, K>]: T[K];
};

这里我们映射 Tstring 相交的键,以确保我们只有字符串键。然后将带有 as 的那些重命名为 StripPrefix<TPrefix, K>,这将 return 无前缀的字符串,或者通过 returning never.[=20= 将其从结果中删除]

并且值类型只是T[K],这是原始前缀属性的值类型。

Playground