[英]Typescript: Infer correct type from string literal union applied on keyed object
I am using MobX and have this repository that contains all entities in my app. 我正在使用MobX,并且该存储库包含我的应用程序中的所有实体。
I want to have two functions 我想要两个功能
But I also want them to be typesafe. 但是我也希望它们是类型安全的。
Let's say that I keep this collection: 假设我保留此收藏集:
@observable entities = {
authors: {} as Record<string, Author>,
comments: {} as Record<string, Comment>,
posts: {} as Record<string, Post>
}
I want to use my function like the following: 我想像下面这样使用我的函数:
// "authors" should be checked against "authors" | "posts" | "comments"
// by specifying "authors" statically, I want typescript to automatically refine the return type to be Author, otherwise Author | Posts | Comment
addEntity("authors", new Author(...))
// same here
getEntity("authors", id)
I have tried many ways with the generics but I can't get it right. 我已经尝试了很多使用泛型的方法,但是我做不到。 I have to add a generic type that I type cast to So my calls are like this:
我必须添加一个类型类型,然后将其类型转换为:
getEntity<Author>("authors")
// but nothing prevents me from writing
getEntity<Author>("posts")
Is there a trick to make this work? 有一个技巧可以使这项工作吗?
Not sure about the MobX part, but the typescript type is a pretty straight forward application of index type queries and keyof
: 不确定MobX部分,但打字稿类型是索引类型查询和
keyof
直接应用:
class Author { id!: string; a!: string }
class Comment { id!: string; c!: string }
class Post {id!: string; p!: string }
class Store {
entities = {
authors: {} as Record<string, Author>,
comments: {} as Record<string, Comment>,
posts: {} as Record<string, Post>
}
}
let store = new Store();
function addEntity<K extends keyof Store['entities']>(type: K, value: Store['entities'][K][string]) {
let collection = store.entities[type] as Record<string, typeof value>; // some type assertions required
collection[value.id] = value;
}
function getEntity<K extends keyof Store['entities']>(type: K, id: string): Store['entities'][K][string] {
let collection = store.entities[type] as Record<string, Store['entities'][K][string]>; // some type assertions required
return collection[id];
}
addEntity("authors", new Author())
addEntity("authors", new Post()) // err
// same here
let a: Author = getEntity("authors", "1")
let p : Post = getEntity("authors", "1") //err
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.