如何使用通用接口?

时间:2019-02-08 14:23:35

标签: typescript interface

我不知道如何将道具的类型链接在一起

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 :(得分:1)

问题是,您需要一个额外的类型参数来保留表示要使用的密钥的实际类型。

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不支持部分类型推断,所以这是我们能做的最好的工作(希望soon可以实现,但该功能看起来像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)} />;

答案 1 :(得分:0)

(value: ItemType[K]) => ItemType[K]定义输入和返回值必须相同。

因此formatter={(val: MyExample['name']) => 'coucou'}无效,因为输入(MyExample [string])和return(string)不同。

所以我认为您应该将(value: ItemType[K]) => ItemType[K]更改为(value: ItemType[K]) => ItemType[K] | string