每个 属性 带有前缀的映射类型

Mapped Type with Prefix for each Property

我想创建一个只允许以给定前缀开头的属性的类型:

const example = {
  '#prop1': () => {},
  '#prop2': () => {}
} 

因此在这种情况下,每个 属性 必须以 # 为前缀。我玩过 »Template Literal Types« within »Mapped Types« 像这样:

interface WithD {
  [s: `#${string}`]: () => void
}

但是会产生这个错误:

An index signature parameter type must be either 'string' or 'number'.

有什么方法可以实现吗?

就像@Nadia Chibrikova 所说的那样,如果事先不知道 example 值,就无法构建 WithD

处理它的唯一方法是知道(能够推断)您要验证的类型。


type Validation<T extends Record<string, any>> = {
  [Prop in keyof T]: Prop extends `#${string}` ? T[Prop] : never
}

type Assert<T, U> = T extends U ? U extends T ? true : false : false


const example1 = {
  '#prop1': () => { },
  '#prop2': () => { },
}

const example2 = {
  ...example1,
  'prop3': () => { }
}

type Example1 = typeof example1;
type Example2 = typeof example2;


type Result1 = Assert<Example1, Validation<Example1>> // true
type Result2 = Assert<Example2, Validation<Example2>> // false


const isValid = <T extends Validation<T>>(arg: T) => { }
isValid(example1) // ok
isValid(example2) // expected error

Playground

因此,TS 应该从函数参数或泛型参数中推断出你的类型