[英]Typescript - Get property of name with string, as generic type
I butchered the title, not sure the technical term for what I want to do.我扼杀了标题,不确定我想做的事情的技术术语。 Type constraints are a bit mind boggling to me at the moment as I learn them in both F# and Typescript simultaneously.
当我同时在 F# 和 Typescript 中学习它们时,类型约束对我来说有点令人难以置信。
I have a variable of interface state that holds lists of every type of data needed on the page我有一个接口状态变量,它包含页面上所需的每种类型数据的列表
interface state{
clients: clients[]
appointments: appointments[]
...
}
const ApplicationState : state = {...}
I want a generic function that can be used to get a specific client, appointment, whatever by id.我想要一个通用函数,可用于通过 id 获取特定客户、约会。
So something that looks like所以看起来像
getData('clients', 2)
I have started by defining a type of allowed properties (if this can be done a better way let me know).我首先定义了一种允许的属性(如果有更好的方法让我知道)。
type entity = "clients" | "appointments"
But would I then be able to get the property of ApplicationState
?但是我能得到
ApplicationState
的属性吗?
So the getData
function could look something like this?那么
getData
函数可能看起来像这样吗?
const getData = (foo: entity, id: number) => {
ApplicationState.magicallyGetPropertyByName.filter(entity => entity.id = foo.id)
}
Is this possible while keeping type inference?在保持类型推断的同时这可能吗?
Thank you谢谢
The main problem here, is that you are not allowed to call filter
on a union like this:这里的主要问题是你不能像这样在联合上调
filter
:
type Clients = {
tag: 'Clients'
id: number
}
type Appointments = {
tag: 'Appointments'
id: number
}
declare const test: Clients[] | Appointments[]
test.filter(elem => elem)
Please see issues/7294 and issues/13097请参阅问题/7294和问题/13097
However, there is a workaround:但是,有一个解决方法:
type Clients = {
tag: 'Clients'
id: number
}
type Appointments = {
tag: 'Appointments'
id: number
}
type State = {
clients: Clients[]
appointments: Appointments[]
}
type Entity = keyof State;
declare const ApplicationState: State
const withState = <
S extends Record<string, { id: number }[]>
>(state: S) =>
<E extends keyof S>(prop: E, id: number) =>
state[prop].filter(entity => entity.id === id)
const getData = withState(ApplicationState);
getData('clients', 2)
Playground As you might have noticed, I have declared State
as a type
instead of interface
. Playground您可能已经注意到,我已经将
State
声明为一种type
而不是interface
。 This is because interfaces
are not indexed by the default.这是因为默认情况下
interfaces
未编入索引。 If you change it back to interface
, withState
will cause an error.如果将其改回
interface
, withState
将导致错误。
In fact, you don't need to know exact types of clients
and appointments
, you just have to make sure that all of these types have common property id
.事实上,您不需要知道
clients
和appointments
确切类型,您只需要确保所有这些类型都具有公共属性id
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.