我们在 TypeScript 中添加类型断言后是否仍然需要类型注释?

huangapple go评论70阅读模式
英文:

Do we need type annotations even after adding type assertions in Typescript?

问题

以下是要翻译的内容:

"在 TypeScript 中,如果我们在变量后面使用 as,我们是否真的需要指定变量的类型呢?

例如:下面的代码给我相同类型的对象。但是,我想知道正确的做法是什么。

const x: Student = {
  name: "John"
}

// 上面的代码与下面的代码相同吗?

const x = {
  name: "John"
} as Student;

// 还是我们需要同时指定类型?

const x: Student = {
  name: "John"
} as Student;

export interface Student {
  name: string,
  id?: string
}

"

英文:

Do we really need to specify the type of a variable if we specify as in Typescript?

For example: The below code gives me same type of Object. But, I wanna know the correct way to do this.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const x: Student = {
  name: &quot;John&quot;
}

// is the above same as below

const x = {
  name: &quot;John&quot;
} as Student;

// or do we need to specify both

const x: Student = {
  name: &quot;John&quot;
} as Student;

export interface Student {
  name: string,
  id?: string
}

<!-- end snippet -->

答案1

得分: 2

类型注解类型断言 服务于不同但部分重叠的需求;确实很少情况下你会同时使用它们。


类型注解 允许你显式选择变量的类型。它经常是不必要的;没有显式的类型注解,变量的类型通常可以通过其初始化值的类型进行推断。如果该值的类型满足你的需求,那么注解基本上是多余的。如果该值的类型不足够,那么注解是有帮助的。例如,在下面的例子中:

const x = { name: "John" }
/* const x: { name: string; } */

编译器会推断 x 的类型为 {name: string}。这是可以赋值给 Student 的,所以根据你的用例,这可能足够:

function acceptStudent(s: Student) { }
acceptStudent(x); // 可行

但如果你愿意的话,也可以使用类型注解:

const x: Student = {
  name: "John"
}

类型注解会进行相对严格的检查。如果你用与其初始化值不兼容的类型对变量进行注解,你将会得到一个错误:

const x: Student = { // 错误!
  id: "John",
}

另一方面,类型断言 允许你声称一个表达式具有特定的类型。这主要用于当你对表达式的类型了解比编译器能够验证的更多时... 你进行断言,尽管编译器无法看到这个断言是真实的。实际上,另一个用例是当你需要故意向编译器撒谎,以便继续进行。同样,它通常也是不必要的,因为编译器对这些表达式的推断类型通常是合理的。但有时你想要改变编译器对表达式类型的看法:

const x = {
  id: "John"
} as Student; // 没有错误

在这里,尽管 {id: "John"} 不是一个有效的 Student,编译器不会抱怨。它足够接近,因此编译器接受了你的断言。


所以这取决于你的需求。一般的建议是:优先使用注解而不是断言,优先使用推断而不是注解。如果推断足够,就使用它。如果不行,那么就进行注解。如果仍然不起作用,那么考虑进行断言(但要小心)。而且同时使用两者几乎肯定是不必要的。一旦你断言了初始化表达式的类型,那么该类型将成为变量的推断类型,因此注解是多余的。

Playground 链接到代码

英文:

Type annotations and type assertions serve different but partially overlapping needs; it's rare indeed that you'd ever want to use both.


A type annotation lets you explicitly choose the type of a variable. It is quite often unnecessary; without an explicit type annotation the variable's type can often be inferred by the type of its initializing value. If that value's type suffices for your needs, then an annotation is essentially redundant. If that value's type is insufficient, then an annotation is helpful. For example in

const x = { name: &quot;John&quot; }
/* const x: { name: string; } */

the compiler infers the type of x as {name: string}. This is assignable to Student, and so depending on your use case it might suffice:

function acceptStudent(s: Student) { }
acceptStudent(x); // works

But you should feel free to use an annotation if you prefer:

const x: Student = {
  name: &quot;John&quot;
}

Type annotations are checked fairly strictly. If you annotate a variable with a type incompatible with its initializer, you'll get an error:

const x: Student = { // error!
  id: &quot;John&quot;,
}

A type assertion on the other hand lets you claim that an expression is of a certain type. This is used primarily when you know more about the type of an expression than the compiler can verify... you assert it, despite the compiler's inability to see that the assertion is true. Actually another use case is when you need to deliberately lie to the compiler about the type of an expression in order to proceed. Again it is also quite often unnecessary, since the compiler's inferred types for such expressions is usually reasonable. But there are times where you want to change the compiler's view about an expression's type:

const x = {
  id: &quot;John&quot;
} as Student; // no error

Here the compiler does not complain, even though {id: &quot;John&quot;} is not a valid Student. It's close enough, though, for the compiler to accept your assertion.


So it depends on what your needs are. The general advice here is roughly: prefer annotations over assertions, and prefer inference over annotations. If inference suffices, then use it. If not, then annotate. If that still doesn't work, then consider asserting (but be careful). And using both is almost certainly overkill. Once you assert the type of an initializing expression, that type will be the inferred type for the variable, and an annotation is therefore redundant.

Playground link to code

huangapple
  • 本文由 发表于 2023年6月2日 06:13:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76386048.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定