打字稿:从应用于键控 object 的字符串文字联合推断出正确的类型
Typescript: Infer correct type from string literal union applied on keyed object
我正在使用 MobX 并拥有包含我应用程序中所有实体的存储库。
我想要两个功能
- addEntity: 获取一个实体并 updates/inserts 它
- getEntity: Returns 未定义的实体
但我也希望它们是类型安全的。
假设我保留这个 collection:
@observable entities = {
authors: {} as Record<string, Author>,
comments: {} as Record<string, Comment>,
posts: {} as Record<string, Post>
}
我想像下面这样使用我的函数:
// "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)
我已经尝试了很多方法来使用泛型,但我做不好。
我必须添加一个泛型类型,我将类型转换为
所以我的电话是这样的:
getEntity<Author>("authors")
// but nothing prevents me from writing
getEntity<Author>("posts")
有什么技巧可以实现吗?
不确定 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
我正在使用 MobX 并拥有包含我应用程序中所有实体的存储库。
我想要两个功能
- addEntity: 获取一个实体并 updates/inserts 它
- getEntity: Returns 未定义的实体
但我也希望它们是类型安全的。
假设我保留这个 collection:
@observable entities = {
authors: {} as Record<string, Author>,
comments: {} as Record<string, Comment>,
posts: {} as Record<string, Post>
}
我想像下面这样使用我的函数:
// "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)
我已经尝试了很多方法来使用泛型,但我做不好。 我必须添加一个泛型类型,我将类型转换为 所以我的电话是这样的:
getEntity<Author>("authors")
// but nothing prevents me from writing
getEntity<Author>("posts")
有什么技巧可以实现吗?
不确定 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