根據 Typescript 中兄弟屬性的泛型類型推斷類型
我想根據其同級屬性的泛型類型來定義一個屬性的類型。
例如,假設我們有:
type Person = {
id: number;
name: string;
}
type Select<Value=unknown> = (props:Props<Value>) => any;
const PersonSelect:Select<Person> = (props) => null //implementation is irrelavant
const TextSelect:Select<string> = (props) => null //implementation is irrelavant
那麼我想要能夠做像這樣的事情:
type Filter<V = unknown > = {
component: Select<V>,
transformer: (value: V) => string
};
const filters:Array<Filter> = [
{
component: PersonSelect,
transformer: (selected) => selected.name //type of `selected` should be infered as `Person`
},
{
component: TextSelect,
transformer: (selected) => selected // type of `selected` should be infered as `string`
}
]
變通方法
使用上述代碼,我可以這樣做
const personFilter:Filter<Person> = {
component: PersonSelect,
transformer: (selected) => selected.name
}
const textFilter:Filter<string> = {
component: TextSelect,
transformer: (selected) => selected
}
const filters = [personFilter, textFilter];
但我正在尋找一種不需要明確定義每個過濾器對象類型的解決方案。此外,泛型 V 類型可以是任何類型,所以我無法使用所有可能組合的聯合。
有沒有更好的解決方案?
答案#1
似乎是 TypeScript 在根據同一對象的其他屬性推斷箭頭函數屬性參數時遇到了困難。
我無法借助函數推斷來完成它。
最簡單的方法是建立一個 builder 函數,該函數返回 Filter<_>。
type Person = {
id: number;
name: string;
}
type Props<T> = T
type Select<Value = unknown> = (props: Props<Value>) => any;
const PersonSelect: Select<Person> = (props) => null //implementation is irrelavant
const TextSelect: Select<string> = (props) => null //implementation is irrelavant
type Filter<V = unknown> = {
component: Select<V>,
transformer: <T extends V>(value: T & V) => string
};
const builder = <V,>(
component: Select<V>,
transformer: (value: V) => string
): Filter<V> =>
({ component, transformer })
const filters = [
builder(PersonSelect, (selected) => selected.name),
builder(TextSelect, (selected) => selected)
]
遊樂場
因為 component 和 transformer 參數不是同一個資料結構的一部分,所以推斷它們並應用我們的類型約束會更容易。
在這裡,你可以找到更多關於函數參數型別推斷的例子。
