ts的类型推论

typescript的类型推论(Type Inference)是指在没有显式标注类型的情况下,编译器自动根据代码的上下文推断出变量、参数、返回值等的类型。这是ts能在保持类型安全的同时减少冗余代码的关键特性。

1.基于初始化的变量推论

当我声明变量并初始化时,Ts就会根据初始值来判断类型。

ts 复制代码
let name = "Alice"; // 推论为 string
let age = 25; // 推论为 number
let isActive = true; // 推论为 boolean
let items = [1, 2, 3]; // 推论为 number[]
let mixed = [1, "a", true]; // 推论为 (number | string | boolean)[]

一旦推断完成,就不能赋值为其他类型了哈。

比如: name =123 错哈 这个是错的 它是不能将number赋值给string哈~

2.函数返回值推论

函数的返回类型如果没有显式标注,Ts会根据return语句推断。

ts 复制代码
function add(a: number, b: number) {
    return a + b; // 推论返回类型为 number
}

function getName() {
    return "Bob"; // 推论返回类型为 string
}

function getPerson() {
    return {
        name: "Charlie",
        age: 30
    }; // 推论返回一个 { name: string; age: number } 对象
}
3.参数类型推论(在上下文中)

在函数调用或赋值时,Ts会根据上下文推断参数类型。

ts 复制代码
// 数组的 map 方法
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);
// TS 知道 numbers 是 number[],所以 map 的参数 n 被推论为 number
ts 复制代码
// 回调函数
document.addEventListener("click", (e) => {
    console.log(e.target); // e 被推论为 MouseEvent
});
4.最佳通用类型(Best Common Type)

当表达式中存在多个类型时,Ts会尝试找到一个"最合适的"公共类型。

ts 复制代码
let arr = [1, "hello", false];
// 推论为 (number | string | boolean)[] ------ 联合类型

let arr2 = [null, "hello"];
// 推论为 (string | null)[]

let arr3 = [0, 1, null];
// 推论为 (number | null)[]

在某些情况下,TS会忽略null或undefined,如果其他类型更"具体"。

ts 复制代码
let arr4 = [1, 2, 3, null]; // 仍可能推论为 number[](取决于 strictNullChecks)
5.上下文类型(Contextual typing)

TS会根据变量被使用的"位置"来推断其类型。

ts 复制代码
window.onmousedown = function(mouseEvent) {
    console.log(mouseEvent.button); // mouseEvent 被推论为 MouseEvent
};

// 函数参数
type Handler = (e: Event) => void;
const handler: Handler = (e) => {
    // e 自动被推论为 Event 类型
    console.log(e.timeStamp);
};
6.结构化类型推论(基于形状)

TS是"结构化类型系统",会根据对象的结构推断类型。

ts 复制代码
const point = {
    x: 10,
    y: 20
};
// 推论为 { x: number; y: number }

function printPoint(p) {
    console.log(`${p.x}, ${p.y}`);
}
// p 的类型在调用时根据传入对象的结构决定
printPoint(point); // OK
printPoint({ x: 5, y: 6 }); // OK
7.泛型中的类型推论

在调用泛型函数时,TS通常能自动推断泛型类型。

ts 复制代码
function identity<T>(arg: T): T {
    return arg;
}

const result = identity("hello");
// T 被推论为 string,result 类型为 string

function reverse<T>(items: T[]): T[] {
    return items.slice().reverse();
}

const reversed = reverse([1, 2, 3]);
// T 被推论为 number,reversed 类型为 number[]
8.解构赋值推论
ts 复制代码
const user = { name: "Alice", age: 30 };
const { name, age } = user;
// name 推论为 string,age 推论为 number

const [first, second] = [1, 2];
// first, second 推论为 number

类型推论的局限性

  • 不能推论 any 的情况:如果 TS 无法确定类型,可能会推论为 any(尤其是在 --noImplicitAny 关闭时)。
  • 复杂逻辑可能推论不准确:例如条件分支中类型可能变宽。
  • 建议显式标注:对于公共 API、复杂函数、返回值,显式标注类型更安全。
相关推荐
用户6387994773051 小时前
每组件(Per-Component)与集中式(Centralized)i18n
前端·javascript
SsunmdayKT1 小时前
React + Ts eslint配置
前端
开始学java1 小时前
useEffect 空依赖 + 定时器 = 闭包陷阱?count 永远停在 1 的坑我踩透了
前端
zerosrat1 小时前
从零实现 React Native(2): 跨平台支持
前端·react native
狗哥哥1 小时前
🔥 Vue 3 项目深度优化之旅:从 787KB 到极致性能
前端·vue.js
青莲8431 小时前
RecyclerView 完全指南
android·前端·面试
青莲8431 小时前
Android WebView 混合开发完整指南
android·前端·面试
GIS之路1 小时前
GDAL 实现矢量数据转换处理(全)
前端
大厂技术总监下海1 小时前
Rust的“一发逆转弹”:Dioxus 如何用一套代码横扫 Web、桌面、移动与后端?
前端·rust·开源
加洛斯1 小时前
SpringSecurity入门篇(2):替换登录页与config配置
前端·后端