javascript - 具有相同键和相似值的两种类型的打字稿类型
问题描述
我有一个将对象作为构造函数参数的类,我想在类上强制执行一个方法以接受一个非常相似的对象。对象具有任意键。
例如,使用此对象进行构造:
{
foo: { type: 'A' },
bar: { type: 'B'}
}
我希望该方法只接受类似形式的对象,即具有相同的键,并且每个键的值类型与初始对象兼容。喜欢:
{
foo: SomeARelatedThing,
bar: SomeBRelatedThing
}
我有一个解决方法,我至少可以强制执行相同的键,然后进行大量类型检查(无论如何都很好!)以确保值实际上匹配。
这是我的用例中的一个人为示例:
type TypeName = 'A' | 'B' | 'C' // ...
class Action<K extends TypeName> {
type: K
constructor(type: K) { this.type = type }
}
type AnyAction = Action<'A'> | Action<'B'> | Action<'C'> // ...
type AProp = { type: 'A' }
type BProp = { type: 'B' }
type CProp = { type: 'C' }
type AnyProp = AProp | BProp | CProp // ...
type PropMap<K extends string> = Record<K, AnyProp>
type ActionMap<K extends string> = Record<K, AnyAction>
class Thing<K extends string> {
props: PropMap<K>
constructor(props: PropMap<K>) { this.props = props }
myMethod<>(actions: ActionMap<K>) { /* ... */ }
}
// type = Thing<'foo' | 'bar'>
const thing = new Thing({
foo: { type: 'A' },
bar: { type: 'B'}
})
// the keys are enforced, but how can the values of foo and bar be enforced, too
thing.myMethod({
foo: new Action('A'),
bar: new Action('B'),
})
我想我想要一个更像等于的类型Thing<{foo: 'A', bar: 'B'}>
,但我不知道如何有条件地从构造函数的PropMap
-like 输入计算它Thing
,或者即使我这样做了,那么我将如何计算正确ActionMap
的 -like 类型。
MyMethod
实际上接受 aPartial<ActionMap<K>>
但我认为这对我的要求并不重要。
解决方案
我想我明白了。您需要使用映射类型。
class Thing<K extends string, P extends PropMap<K>> {
props: P
constructor(props: P) { this.props = props }
myMethod(actions: {[Property in keyof P]: Action<P[Property]["type"]>}) { return actions }
}
const thing = new Thing({
foo: { type: 'A' },
bar: { type: 'B'}
})
// the keys are enforced, as well as the corresponding Action types
thing.myMethod({
foo: new Action('A'),
bar: new Action('B'),
})
请注意,您需要将泛型添加P
到您的类中,否则 TypeScript 在您稍后Thing
实例化时无法推断出更详细的信息。Thing
基本上,您需要将其设置P
为一致的泛型类型, Thing
否则无法将PropMap
其与其扩展的类型区分开来。
然后,魔术发生在actions: {[Property in keyof P]: Action<P[Property]["type"]>}
. 让我们分解一下:
[Property in keyof P]:
映射类型索引签名。这就是让我们可以访问 中的特定键的原因P
,例如foo
,bar
等。Action<...>
将与我们在上面 (1.) 中映射的每个键对应的值设置为某个值,我们希望将其设置为Action
等Action<'A'>
。但我们希望操作从 的原始值派生P
,所以...P[Property]["type"]
让我们type
从原始类型的键/值对中访问值P
。由于Property
变化(它从一种类型映射到另一种类型),因此例如它变成foo: P["foo"]["type"]
which is'A'
,bar: P["bar"]["type"]
which is'B'
等
推荐阅读
- python - 如何在“Tattoo”文本中执行 Playfair cypher?
- r - 如何用月份的全名替换数字月份
- python - django-admin正在执行,但virual目录中没有创建项目
- apache-kafka - 回复 Kafka 模板 - 异常处理
- amazon-cloudformation - 在 ECS 中使用应用程序负载均衡器的 504 网关超时
- django - 如何在表单中定义电话号码和模板错误获取:django.template.exceptions.TemplateDoesNotExist:phone_field/phone_widget.html?
- c# - Postman - 如何使用 V2 端点将用户导入 BIM 360 项目
- c++ - C++ 中的错误消息:函数/变量“未在此范围内声明”,变量“是私有的”
- reactjs - 如果文本值中有表情符号,则 TextInput 样式不会更新
- firebase - Firebase认证,IOS导致PlatformException