TypeScript: чтение универсального типа значения в объекте - PullRequest
3 голосов
/ 19 июня 2019

У меня есть этот интерфейс:

interface Api {
  state: Converter<State>;
  water: Converter<Water>;
  version: Converter<Versions>;
}

и у меня есть функция с именем write

write(name, value);

Теперь я хочу добиться того, чтобы тип value был общим для Converter в зависимости от первого параметра (name).

Так что, если я позвоню write("state", value) -> value должно быть State. То же самое касается "water" и "version".

write("state, value);    // value should be type of State
write("water", value);   // value should be type of Water
write("version", value); // value should be type of Versions

Я реализовал первый параметр примерно так:

write(name: keyof Api, value: ???)

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

write<K extends keyof Api>(name: K, value: Api[K])

но это дает мне Converter<State> за "state". Есть ли способ получить доступ к универсальному в Converter?

Ответы [ 2 ]

3 голосов
/ 19 июня 2019

если у вас есть доступ к интерфейсу / типу конвертера или к какому-либо другому расширению этого типа

или создайте расширенный интерфейс, подобный этому

interface Converter<T> {
  p1: any;
  p2: any;
}
interface IExtendedConverter<T> extends Converter<T> {
  type: T;
}

interface IApi {
  state: IExtendedConverter<string>;
  water: IExtendedConverter<number>;
}

const write = <K extends keyof IApi>(name: K, value: IApi[K]['type']) => {
  return;
};

const str = write('state', '1'); // here value has to be string
const num = write('water', 1); // here value has to be number

РЕДАКТИРОВАТЬ на основе вопроса

одно решение будет определять этот параметр

const extendedConverterState: IExtendedConverter<string> = {
  ...converter,
  type: '',
};

const extendedConverterNumber: IExtendedConverter<number> = {
  ...converter,
  type: 1,
};

const api: IApi = {
  state: extendedConverterState,
  water: extendedConverterNumber,
};

это решение с некоторой задержкой, так как вы просто создадите это свойство, которое никогда не будет использовано.

Другим решением может быть создание параметра типа как опция

interface IExtendedConverter<T> extends Converter<T> {
  type?: T;
}

но этот соулитон установит ваш параметр в функции записи как необязательный (возможно, неопределенный)

ну, может быть, есть лучшее решение для доступа к этому универсальному типу ИДК

0 голосов
/ 19 июня 2019

Я не знаю, помогает ли это, так как я не уверен, как выглядит ваш Converter интерфейс.

Но с этим:

interface Converter<T> {
  converter: T;
}

И эти интерфейсы для State, Water и Version:

interface State {
  state: string;
}

interface Water {
  water: string;
}

interface Version {
  version: string;
}

Вы можете сделать это:

function write<K extends keyof Api>(name: K, value: Api[K]["converter"]) {}
write("state", { state: "x" }); // Works

write("water", { state: "x" }); // Argument of type '{ state: string; }' is not assignable to parameter of type 'Water'.

write("water", { water: "x" }); // Works

Но он добавляет свойство к вашему Converter интерфейсу.

...