Проблема в том, что вам нужен дополнительный параметр типа, чтобы сохранить фактический тип, который будет представлять используемый ключ.
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)} />;