属性 在 Typescript 中索引其他 属性
Property that indexes other property in Typescript
我有以下类型:
interface CellsReducer {
source: number;
destination: number;
plan: string;
duration: number;
test: []
}
interface BarReducer {
baz: string;
}
interface AppState {
cells: CellsReducer;
bar: BarReducer;
}
我想用以下对象编写一个接口:
interface Props {
store: keyof AppState;
field: // AppState[store]
data: // AppState[store][field]
}
使用泛型对我没有任何帮助。 fields
在以下示例中以类型 never
结束:
type Stores<T> = keyof T;
type Fields<T> = keyof T[Stores<T>];
type Props<TState> = {
state: Stores<TState>;
field: Fields<TState>
}
有办法吗?
路径中的每个 属性 都需要不同的类型参数。这允许编译器推理您指定的特定字段:
type Props<TState, KStore extends keyof TState, KField extends keyof TState[KStore]> = {
state: KStore;
field: KField
data: TState[KStore][KField]
}
let p: Props<AppState, "cells", "duration"> = {
state: "cells",
field: "duration",
data: 1
}
你得到 never 的原因是当编译器试图扩展 AppState[keyof AppState]
时它会得到一个联合 CellsReducer | BarReducer
。由于只有 union 的普通成员是可访问的 keyof (CellsReducer | BarReducer)
是 never
(没有键是可访问的)。
额外参数捕获实际字段,因此如果 KStore
是字符串文字类型 "cells"
keyof AppState["cells"]
将是应用状态中该特定字段的键。 KField
的工作方式类似,允许我们正确输入 data
.
为避免指定 state
和 field
值两次,您可以编写辅助函数:
function propertyFactory<TState>() {
return function <KStore extends keyof TState, KField extends keyof TState[KStore]>(o: Props<TState, KStore, KField>) {
return o;
}
}
let p = propertyFactory<AppState>()({
state: "cells",
field: "duration",
data: 1
})
你的意思是:
interface Props<T, K extends keyof T, V extends keyof T[K]> {
state: keyof T;
field: T[K];
data: T[K][V]
}
用法:
const props: Props<AppState, 'cells', 'plan'> = { /* ... */ } ;
const props: Props<AppState, 'bar', 'baz'> = { /* ... */ } ;
我有以下类型:
interface CellsReducer {
source: number;
destination: number;
plan: string;
duration: number;
test: []
}
interface BarReducer {
baz: string;
}
interface AppState {
cells: CellsReducer;
bar: BarReducer;
}
我想用以下对象编写一个接口:
interface Props {
store: keyof AppState;
field: // AppState[store]
data: // AppState[store][field]
}
使用泛型对我没有任何帮助。 fields
在以下示例中以类型 never
结束:
type Stores<T> = keyof T;
type Fields<T> = keyof T[Stores<T>];
type Props<TState> = {
state: Stores<TState>;
field: Fields<TState>
}
有办法吗?
路径中的每个 属性 都需要不同的类型参数。这允许编译器推理您指定的特定字段:
type Props<TState, KStore extends keyof TState, KField extends keyof TState[KStore]> = {
state: KStore;
field: KField
data: TState[KStore][KField]
}
let p: Props<AppState, "cells", "duration"> = {
state: "cells",
field: "duration",
data: 1
}
你得到 never 的原因是当编译器试图扩展 AppState[keyof AppState]
时它会得到一个联合 CellsReducer | BarReducer
。由于只有 union 的普通成员是可访问的 keyof (CellsReducer | BarReducer)
是 never
(没有键是可访问的)。
额外参数捕获实际字段,因此如果 KStore
是字符串文字类型 "cells"
keyof AppState["cells"]
将是应用状态中该特定字段的键。 KField
的工作方式类似,允许我们正确输入 data
.
为避免指定 state
和 field
值两次,您可以编写辅助函数:
function propertyFactory<TState>() {
return function <KStore extends keyof TState, KField extends keyof TState[KStore]>(o: Props<TState, KStore, KField>) {
return o;
}
}
let p = propertyFactory<AppState>()({
state: "cells",
field: "duration",
data: 1
})
你的意思是:
interface Props<T, K extends keyof T, V extends keyof T[K]> {
state: keyof T;
field: T[K];
data: T[K][V]
}
用法:
const props: Props<AppState, 'cells', 'plan'> = { /* ... */ } ;
const props: Props<AppState, 'bar', 'baz'> = { /* ... */ } ;