与仅使用接口相比,此返回类型与Never Do有什么区别? [英] What does this return type with never do vs just using an Interface?
问题描述
在尝试用TypeScrip创建工厂时,我遇到了this article,我被这部分搞糊涂了:
class UserFactory {
static getUser(k: Keys) : ExtractInstanceType<userTypes> {
return new userMap[k]();
}
引用的类型定义:
type ExtractInstanceType<T> = T extends new () => infer R ? R : never;
我不确定为什么我们需要ExtractInstanceType&&为什么我们不想只使用IStaff:
class UserFactory {
static getUser(k: Keys) : IStaff {
return new userMap[k]();
}
我也不知道Keys在这里说的是什么,我以为它只是UserMap可以保存的词典中的一个键,应该是一个字符串?
但当使用该方法时,它是与对象实例一起用作其参数还是不可能使用?
const manager = new Manager();
const anotherManger = UserFactory.getUser(manager);
推荐答案
我不确定为什么需要ExtractInstanceType&;为什么不只使用IStaff?
因为userMap
和关联的静态方法的全部要点是将名称映射到特定的、具体的类,而不是它们实现的接口。如果这些类中的任何一个在一般的IStaff接口之上实现特定于类的东西(它们几乎肯定会实现),那么每次您调用一个不在IStaff
中的方法时,如果您没有通过使用该静态方法缩小类型以满足编译器的要求来将其扼杀在萌芽状态,那么您的代码将充满instanceof
或其他检查。
我以为它只是UserMap可以保存的词典中的一个键,应该是一个字符串?
正如我在我对您的other question回答的评论中所建议的,我认为问题在于您仍在混淆类型和值。但有些重叠也无济于事。
考虑字符串‘a’。在TypeScrip中,有值‘a’,但也有文本类型‘a’,它是string
类型的子集:
type a = 'a'
let a: a = 'a'
let s: string = a // note, variable a not string literal a!
const foo = {
a: 1
}
console.log(foo[a]) // 1
console.log(foo[s]) // type error!
// ok, let's try the string literal 'a'
s = 'a'
console.log(foo[s]) // same type error!
// eff
由于a
从字面上看是‘a’,我们可以用它为foo
编制索引。但是s
是字符串的可变绑定,即使我们将值设置为‘a’,而且即使我们将值设置为变量a
,类型为a,s
仍然字符串,编译器也无法保证我们不会重新分配非a值。playground
类型可能类似于值,并且在某些上下文中可能具有与值完全相同的外观,但它们不是非值类型,也不是值类型。一直往前走...
对于我们在编译时知道的对象文字,对象中的键,所以如果我们有一个foo对象{a: 'hi', b: 5}
,那么keyof typeof foo
就是'a' | 'b'
。注:这些是字符串,但在本例中,它们是类型,而不是Java脚本值。博文中的方法将k
参数可以传递的值限制为userMap
的编译时已知键中的值。
但当使用该方法时,它是与对象实例一起用作其参数还是不可能使用?
哦,有可能将方法更改为以那种方式工作,这是没有意义的。如果您有对一个实例的引用,那么您已经有了对其构造函数的引用,您不需要查找表来创建另一个:
class Foo {}
const foo = new Foo()
const bar = new (foo.constructor as any)()
bar instanceof Foo // true
同样,userMap
和访问它的静态方法的要点是工厂能够通过字符串名查找正确的User类。
这篇关于与仅使用接口相比,此返回类型与Never Do有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!