是否可以从接口/类型中过滤掉键?

Is it possible to filter out keys from an interface / type?

比如我有一个接口:

interface Foo {
  name: string;
  id: number;
}

我只想要 string 类型的键。我设法将 id 的类型更改为 never 并从 Foo 获取了所有密钥。但是 id 仍然是一个有效的密钥,只是类型 never.

const bar: keyof Partial<{ [K in keyof Foo ]: Foo [K] extends string ? Foo [K] : never }> = 'id';

如何仅从 Foo 类型的 string 中获取密钥?

我想要的是:

const bar: FooStringKeys = 'name'; // ok
const bar: FooStringKeys = 'id;    // error

采纳自 mapped types docs. TS Playground version here

interface Foo {
  name: string;
  id: number;
}

// Generic string property extractor
type StringsOnly<Type> = {
    [Property in keyof Type as Extract<Property, Type [Property] extends string ? Type [Property] : never>]: Type[Property]
};

// Foo *string* Properties
type FooString = StringsOnly<Foo>

const fooString: FooString = {name: 'hello'}
const notFooString: FooString = {id: 2} // error

// Foo *string* Key names
type FooStringKey = keyof FooString

const fooStringKey: FooStringKey = "name"
const notFooStringKey: FooStringKey = "id" // error