Typescript type assertions

TypeScript allows you to override its inference and analyze it any way you want, a mechanism called "type assertion". TypeScript type assertions are used to tell the compiler that you know the type better than it does, and that it shouldn't throw errors anymore.

A common use case for type assertions is when you're migrating from JavaScript to TypeScript:

const foo = {};
foo.bar = 123; // Error: 'bar' 属性不存在于 ‘{}’
foo.bas = 'hello'; // Error: 'bas' 属性不存在于 '{}'

The code here gives an error warning because  foo the type of 's is inferred  {}, i.e. an object with no properties. So you can't add  bar or  on its properties bas, you can avoid this problem with type assertion:

interface Foo {
  bar: number;
  bas: string;
}

const foo = {} as Foo;
foo.bar = 123;
foo.bas = 'hello';

#withas foo  _ <foo>

The initial assertion syntax looks like this:

let foo: any;
let bar = <string>foo; // 现在 bar 的类型是 'string'

However, when you use  <foo> the assertion syntax in JSX, this is ambiguous with the JSX syntax:

let foo = <string>bar;</string>;

Therefore, for consistency, we recommend that you use  as foo the syntax for type assertions.

#Type assertion and type conversion

The reason it's not called "type conversion" is because conversion usually implies some kind of runtime support. However, a type assertion is purely a compile-time syntax, and at the same time, it is a way for the compiler to know how to analyze the code.

#Type assertions are considered harmful

In many cases, assertions can make it easier to migrate from legacy projects (or even paste-copy other code into your project), however, you should use assertions with care. Let's use the original code as an example, if you don't add the property by convention, the TypeScript compiler doesn't give an error about it:

interface Foo {
  bar: number;
  bas: string;
}

const foo = {} as Foo;

// ahhh, 忘记了什么?

Another common idea is to use type assertions to provide code hints:

interface Foo {
  bar: number;
  bas: string;
}

const foo = <Foo>{
  // 编译器将会提供关于 Foo 属性的代码提示
  // 但是开发人员也很容易忘记添加所有的属性
  // 同样,如果 Foo 被重构,这段代码也可能被破坏(例如,一个新的属性被添加)。
};

This also has the same problem, if you forget a property, the compiler will also not issue an error warning. Use a better way:

interface Foo {
  bar: number;
  bas: string;
}

const foo: Foo = {
  // 编译器将会提供 Foo 属性的代码提示
};

In some cases you may need to create a temporary variable, but at least, you won't use a promise (which may be false) and rely on type inference to check your code.

# double assertion

Type assertions, even though we've shown that they're not that safe, have their place. As shown in a very useful example below, type assertions work as expected when the user knows the more specific type of the incoming parameter:

function handler(event: Event) {
  const mouseEvent = event as MouseEvent;
}

However, the code in the following example will report an error even though the user has used type assertions:

function handler(event: Event) {
  const element = event as HTMLElement; // Error: 'Event' 和 'HTMLElement' 中的任何一个都不能赋值给另外一个
}

If you still want to use that type, you can use a double assertion. First assert to be compatible with all types  any, the compiler will not report an error:

function handler(event: Event) {
  const element = (event as any) as HTMLElement; // ok
}

# How TypeScript determines if a single assertion is enough

 Can be successfully asserted  when  a S type is  T a subset of a type, or  T a type is  S a subset of a type . This is to provide extra safety when making type assertions, completely unwarranted assertions are dangerous and you can use if you want to  .STany

Guess you like

Origin blog.csdn.net/z591102/article/details/120011068