简体   繁体   English

TypeScript:差异通用约束 VS 参数类型

[英]TypeScript: Difference Generic Constraints VS Parameter Type

I do not understand the difference between Generic Constraints and plain Parameter Types.我不明白通用约束和普通参数类型之间的区别。 In the first case, I do understand that I cannot call si.g() because I strictly typed si to be of type SomeInterface.在第一种情况下,我确实明白我不能调用 si.g() 因为我严格地将 si 键入为 SomeInterface 类型。 However, in the second example S extends SomeInterface and from my explanation , extending means it needs to have f() but can contain more properties.但是,在第二个示例中, S 扩展了 SomeInterface ,根据我的解释,扩展意味着它需要具有 f() 但可以包含更多属性。 But the error is the same.但错误是一样的。 Why?为什么?

interface SomeInterface {
    f();
}

function test1(si: SomeInterface) {
    si.f()
    // si.g() -> Property 'g' does not exist on type 'SomeInterface'
}

function test2<S extends SomeInterface>(si: S) {
    si.f()
    // si.g() -> Property 'g' does not exist on type 'SomeInterface'
}

Typescript needs to check that you're passing a type that includes the function g . Typescript 需要检查您传递的类型是否包含函数g So you need to do something like this:所以你需要做这样的事情:

interface ExtendedInterface extends SomeInterface {
 g();
}

...

function test2<E extends ExtendedInterface>(ei: E) {
    si.f()
    si.g()
}

Of course, you can also do this:当然,你也可以这样做:

function test3(ei: ExtendedInterface) {
    ei.g();
    ei.f();
}

And that'll be functionally identical to the version with generics.这在功能上与带有泛型的版本相同。

So what's the difference?那么有什么区别呢? Nothing here, but generics give you more power at the expense of more complex code.这里没有什么,但是泛型以更复杂的代码为代价为您提供了更多的功能。 For example, generics allow you to declare a type parameter that is constrained by another type parameter.例如,泛型允许您声明受另一个类型参数约束的类型参数。

...extending means it needs to have f() but can contain more properties. ...扩展意味着它需要有 f() 但可以包含更多属性。 But the error is the same.但错误是一样的。 Why?为什么?

Because it may or may not have more properties, and if it does, they may have any name or any type.因为它可能有也可能没有更多的属性,如果有,它们可能有任何名称或任何类型。 TypeScript doesn't know what those properties are, so inside test2 , TypeScript only knows that si is a SomeInterface . TypeScript 不知道这些属性是什么,所以在test2 ,TypeScript 只知道siSomeInterface

You opened by saying you didn't understand the difference between type parameters ( <S extends SomeInterface> and si: S ) vs. just putting types on parameters ( si: SomeInterface ).您首先说您不了解类型参数( <S extends SomeInterface>si: S )与仅将类型放在参数上( si: SomeInterface )之间的si: SomeInterface Type parameters let you do more interesting things, like:类型参数让你做更多有趣的事情,比如:

function pluck<Type extends object, Key extends keyof Type>(array: Type[], key: Key) {
    return array.map(element => element[key]);
}

const objects = [{a: 2, b: "s"}, {a: 3, b: "x"}];
const x = pluck(objects, "a"); // `x` is `number[]`
const y = pluck(objects, "b"); // `y` is `string[]`

Playground link 游乐场链接

I could be mistaken, but I don't think you can do that without type parameters (or type assertions).我可能弄错了,但我认为如果没有类型参数(或类型断言),您就无法做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM