Как использовать универсальный интерфейс? - PullRequest
0 голосов
/ 08 февраля 2019

Я не могу понять, как мне связать типы моих реквизитов

interface MyExample {
    id: number;
    name: string;
}
export interface ListItemProps<ItemType> {
    value: keyof ItemType;
    formatter?: <K extends keyof ItemType>(value: ItemType[K]) => ItemType[K];
}

const ListItem = <T extends {}>(props: ListItemProps<T>) => null;

export default ListItem;

Так что, когда я делаю

<ListItem<MyExample> value="name" formatter={(val: string) => val.toUpperCase()} />
<ListItem<MyExample> value="id" formatter={(val: number) => String(id)} />

Это не должно предупреждать меня оформатер.

На самом деле я получил: a busy cat

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

(value: ItemType[K]) => ItemType[K] определяет, что входное и возвращаемое значение должны быть одинаковыми.

Следовательно, formatter={(val: MyExample['name']) => 'coucou'} недопустимо, поскольку input (MyExample [string]) и return (string) не совпадают.

Так что я думаю, вы должны изменить (value: ItemType[K]) => ItemType[K] на (value: ItemType[K]) => ItemType[K] | string

0 голосов
/ 08 февраля 2019

Проблема в том, что вам нужен дополнительный параметр типа, чтобы сохранить фактический тип, который будет представлять используемый ключ.

interface MyExample {
    id: number;
    name: string;
}
export interface ListItemProps<ItemType, K extends keyof ItemType> {
    value: K;
    formatter?: (value: ItemType[K]) => string;
}

const ListItem = <T extends {}, K extends keyof T>(props: ListItemProps<T, K>) => null;


let s = <ListItem<MyExample, "name"> value="name" formatter={(val) => val.toUpperCase()} />
let s2 = <ListItem<MyExample, "id"> value="id" formatter={(val) => val.toFixed(4)} />

В идеале value может быть выведено из использования, а TS - нет.поддержка частичного вывода типа, так что это лучшее, что мы можем сделать (надеюсь, скоро , но эта функция выглядит так, как будто она будет не только для JSX-тегов вначале)

Если мы не будемНе возражая против использования HOC, мы могли бы также написать:

interface MyExample {
    id: number;
    name: string;
}
export interface ListItemProps<ItemType, K extends keyof ItemType> {
    value: K;
    formatter?: (value: ItemType[K]) => string;
}

const ListItem = <T extends {}>() => <K extends keyof T>(props: ListItemProps<T, K>) => null;

const MyExampleListItem = ListItem<MyExample>();
const s = <MyExampleListItem value="name" formatter={(val) => val.toUpperCase()} />;
const s2 = <MyExampleListItem value="id" formatter={(val) => val.toFixed(4)} />;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...