Keyof也是T型

Rob*_*bus 10 typescript

有没有办法限制,keyof T以便它只接受某种类型的键?假设如下:

interface Something {
    id: number;  
    name: string;  
    value1: FancyType;  
    value2: FancyType;  
    value3: FancyType;
}

function someFunction(key: keyof Something) {
   // do something to a FancyType
}
Run Code Online (Sandbox Code Playgroud)

someFunction会接受id | name | value1 | value2 | value3,有没有办法将它限制为类型的键FancyType,即value1 | value2 | value3

Mot*_*tti 10

从TypeScript 2.8开始,这可以通过条件类型(Code)实现.

type FancyProperties<T> = Pick<T, { 
    [K in keyof T]: T[K] extends FancyType ? K : never 
}[keyof T]>;


function someFunction(key: keyof FancyProperties<Something>) {
   // do something to a FancyType
}

someFunction("id"); // Error
someFunction("value2"); // OK
Run Code Online (Sandbox Code Playgroud)

  • @JørgenTvedt,如果你只是说“x:Something”而不是“x”上的通用函数,那么该函数就可以工作。`function someFunction1(x: Something, key: keyof FancyProperties&lt;Something&gt;): FancyType { return x[key]; } }`。我想对于编译器来说,使用泛型会使逻辑变得过于复杂。 (2认同)

Gob*_*ain 6

@Motti 答案的更好实现是这样的:

type FilteredKeyOf<T, TK> = keyof Pick<T, { [K in keyof T]: T[K] extends TK ? K : never }[keyof T]>;
Run Code Online (Sandbox Code Playgroud)

它使用与使用条件类型和相同的原则never,但参数化了您的属性应扩展到的类型TK

您可以更灵活地使用它:

function someFunction(key: FilteredKeyOf<Something, FancyType>) {
  // do something to a FancyType
}
someFunction("id"); // error
someFunction("value2"); // okay
Run Code Online (Sandbox Code Playgroud)