Динамически устанавливаемые типы возврата на основе переданных ключей интерфейса - PullRequest
0 голосов
/ 30 марта 2020

Я хочу, чтобы функция возвращала объект, ключи которого равны массиву ключей интерфейса, переданного функции.

interface T { /* ...*/ }
func(keys: Array<keyof T>) => Object whose keys exactly match the argument `keys`.

Пример:

interface Student {
  name: string;
  age: number;
  id: number;
}

const result = func(['name', 'age']);
result.name // ok
result.age // ok
result.id // should be an error

Вот ближе всего я получил с реальным кодом, но он не работает.

class PersonInfo { constructor(field: string){} }

type GetInfo<T> = (fields: Array<keyof T>) => Record<keyof T, PersonInfo>;

const getInfo: GetInfo<Student> = (fields: Array<keyof Student>): Record<keyof Student, PersonInfo> => {
  const result: Record<keyof Student, PersonInfo> = {}; // Compile error because it doesn't contain all keys of Student.
  for (const field of fields) {
    result[field] = new PersonInfo(field);
  }

  return result;
};

const info = getInfo(['name', 'age']);
info.name // ok
info.age // ok
info.id // should be an error, but it's not

Я также попробовал следующее, но, конечно, не скомпилируется, поскольку keyof нельзя использовать со значением.

type GetInfo<T> = <U extends keyof T>(fields: Array<keyof T>) => { [key in keyof fields]: string };

Как я могу ссылаться на содержимое массив который передается в функцию?

1 Ответ

0 голосов
/ 30 марта 2020
interface Student {
  name: string;
  age: number;
  id: number;
}

function getInfo<T extends keyof Student>(keys: T[]): Pick<Student, T> {
  // your impl ..
}

const info = getInfo(['name']);

info.name; // ok
info.id; // TS2339: Property 'id' does not exist on type 'Pick<Student, "name">'.
...