SoFunction
Updated on 2025-03-10

TypeScript type inference and type assertion instance detailed explanation

1. Type Reason

Type inference, as the name suggests, refers to where the type is inferred. In TS syntax, if there is no place to clearly indicate the type, type inference will help provide the type, that is, if the variable is declared, type inference will be triggered.

1. The best general type

The best general type means that in one or more expressions, the type of a variable infers a most suitable general type from all of these expressions.

For example:

let brand = 'YSL'
brand = 123

When defining a variablebrand, the type of the variable brand is inferred as a string, but later modify the value to another type, such as number, boolean, etc. TS will be very considerate to prompt that other types cannot be assigned to the string. However, this is just inferred from a single expression. What if it is multiple expressions? How will we infer? For example:

let money = [1, 'yuan', null]
money = [123]
money = ['hello']
money = [null]​
​
money = [{ name: 'ducky' }]//Error message

It can be seen that when you need to infer a type from several expressions, the types of these expressions will be used to infer a most suitable general type - called the best general type. When there are multiple expressions,moneyThe types of all elements must be considered. Here are three options:numberstringandnull. The calculation general type algorithm takes into account all candidate types and gives a type that is compatible with all candidate types. So how should we infer if the type you want is not on the shortlist? For example:

function Animal() {
    ('animal');
}
function Food() {
    ('food');
}
function Fruit() {
    ('fruit');
}
let target= [new Animal(), new Food(), new Fruit()]

If you want totergetThe type ofPeople[]Type, but there are three candidate types in the array, noPeople[]Type, this is certainly impossible to infer the result. So what should I do? In this case, when the candidate type cannot be used, we must clearly point out the type:

let target:People[]= [new Animal(), new Food(), new Fruit()]

At this time, if the best general type is not found,targetWill be inferred as a union array type:(Animal|Food|Fruit)[]

2. Context Type

The context type depends on the type of the expression and its location, for example:

 = function(e) {
    (e);  //Error message};

An error message will appear:[ts] Parameter :'e' implicitly has an 'any' type, but a better type may be inferred from usage., TS type checker uses the function type to infer the type of the function expression on the right, thus deducingeThe type of parameter, if the function expression is not in the context type, the parameterehaveanytype. We know that any represents any type, which can be assigned by any type, or can be assigned to any type; any type, is a subtype of all types, when assignedanyWhen it is of type, it means it is the same as JS running. So how to change it here? Since it has been promptedehaveanyType, then it's cleareThe type ofanyThat's fine. Once this function expression has clear parameter type annotations, the context type will be ignored.

2. Type Assertion

Type assertions refer to: when we are not sure which type of a joint type variable is, we can only access the properties or methods shared in all types of the union type, but sometimes we need to access the properties and methods of one of the types without even determining the type. Type assertions can be used to manually specify the type of a value.

Type assertions are not types conversions, and asserting that a type that does not exist in a union type is undoubtedly not allowed.

Syntax: <type> value or value as type.

For example:

function getFullName(fullname: string | number): number {
    if () {
        return ;
    } else {
        return ().length;
    }
}
getFullName('hhhhhhhhh')

As shown in the above code, it seems that there is no problem with the logic, but it will report an error to youProperty 'length' does not exist on type 'string | number'. At this time, it is definitely not written in JS, but the code is executed smoothly through type assertions. The modification is as follows:

function getFullName(fullname: string | number): number {
    // if ((<string>fullname).length) {
    if (fullname as string) {
        return (<string>fullname).length
    } else {
        return ().length
    }
}
getFullName('hhhhhhhhh')

Then understanding the following code will definitely be a piece of cake for you ~:

let greet: any = 'hello'
let greetLength1: number = (<string>greet).length
let greetLength2: number = (<string>greet).length
(greetLength1);//5
(greetLength2);//5
​
interface Ob1 {
    name: string,
}
interface Ob2 {
    name: number,
}
let myOb: Ob1 | Ob1 = {
    name: '123'
}
let obLength: number = (<string>).length
(obLength);//3

Attachment: Type alias

type Name = string;
type NameResolver = () =&gt; string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n;
    } else {
        return n();
    }
}

Summarize

This is the article about TypeScript type inference and type assertion. For more related contents of TS type inference and type assertion, please search for my previous articles or continue browsing the related articles below. I hope you will support me more in the future!