ts的真正意义在于,明确类型,提升安全性和可维护性。
1.基础类型
布尔:true/false
let isShow:boolean = false;
数字:支持十进制,十六进制,二进制,八进制。
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
字符串:string类型,可使用双引号""和单引号''。
let name :string ="ly"
name ="ly"
可以使用模版字符串,它可以定义多行文本和内嵌表达式。 这种字符串是被反引号包围( `),并且以${ expr }这种形式嵌入表达式。
let name: string = `ly`;
let hobby: string = `play games`;
let all: string = `hello,my name is ${name},my hooby is ${hobby};`;
console.log(all);
let mease: string = "Hello, my name is " + name +","+ "my hobby is" + hobby+";";
console.log(mease)
数组:两种方式。
第一种,可以在元素类型后面接上 [],表示由此类型元素组成的一个数组:
let list: number[] = [1, 2, 3];
console.log(list)
第二种方式是使用数组泛型,Array<元素类型>:
let list :Array<number>=[1,2,3];
console.log(list)
元祖 Tuple
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string和number类型的元组。
let x: [string, number];
x = ["hello", 10];
x = [10, "hello"];
//.substr() 是 字符串(string) 的方法
console.log(x[1].substr(1));
//number.toFixed(digits)格式化数字的小数位数
console.log(x[0].toFixed(2));
let num = 12.3456;
console.log(num.toFixed(0)); // "12" → 没有小数位
console.log(num.toFixed(1)); // "12.3" → 保留1位小数
console.log(num.toFixed(2)); // "12.35" → 保留2位,自动四舍五入
console.log(num.toFixed(3)); // "12.346" → 保留3位,四舍五入
console.log(num.toFixed(4)); // "12.3456"
枚举
默认情况下是从0开始为元素编号的。
enum Color {
Red,
Green,
Blue,
}
let a: Color = Color.Red;
console.log(a);
let b: Color = Color.Green;
console.log(b);
let c: Color = Color.Blue;
console.log(c);
你可以手动的指定成员的数值。
enum Color {
Red = 1,
Green,
Blue,
}
let a: Color = Color.Red;
console.log(a);
let b: Color = Color.Green;
console.log(b);
let c: Color = Color.Blue;
console.log(c);
或者你可以手动赋值:
enum Color {
Red = 1,
Green = 2,
Blue = 4,
}
let a: Color = Color.Red;
console.log(a);
let b: Color = Color.Green;
console.log(b);
let c: Color = Color.Blue;
console.log(c);
枚举类型提供的一个遍历是你可以由枚举的值得到它的名字。
enum Color {Red = 1, Green, Blue}
let colorNamea: string = Color[1];
let colorNameb: string = Color[2];
let colorNamec: string = Color[3];
console.log(colorNamea);
console.log(colorNameb);
console.log(colorNamec);
举例子:
<template>
<div>
<button @click="checkStatus(OrderStatus.Shipped)">点击测试:已发货</button>
<button @click="checkStatus(OrderStatus.Pending)">点击测试:待发货</button>
</div>
</template>
<script setup lang="ts">
//枚举
enum OrderStatus {
Pending = "pending",
Shipped = "shipped",
Delivered = "delivered",
Cancelled = "cancelled",
}
function checkStatus(status: OrderStatus) {
switch (status) {
case OrderStatus.Shipped:
console.log("已发货");
break;
case OrderStatus.Pending:
console.log("待发货");
break;
default:
console.log("其他状态:", status);
}
}
</script>
Any
在不清楚类型的变量指定一个类型,那可以用any,(临时用下),在知道的情况下,给我改成string,number,interface等明确的类型;
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false;
更好的替代方案:不用any也能处理“类型不清楚”的情况 1.使用unknowm(推荐!比any安全)
let data: unknown = fetchDataFromAPI();
if (typeof data === "string") {
console.log(data.toUpperCase());
}
if (Array.isArray(data)) {
console.log(data.length);
}
2.使用接口(interface)或类型别名(type)描述结构。
interface User {
name: string;
age: number;
isActive?: boolean;
}
let user: User = { name: "Gene", age: 37 };
3.使用联合类型(Union Types)
let id: string | number = "123";
id = 123;
function printId(id: string | number) {
if (typeof id === "string") {
console.log(id.toUpperCase());
} else {
console.log(id.toFixed(0));
}
}
4.使用泛型(Genneric)
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("hello"); // T 就是 string
Void
“这个函数/回调/操作,只负责执行,别指望它返回有用的东西。”
某种程度上来说,void类型像是与any类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void:
//某种程度上来说,void类型像是与any类型相反,它表示没有任何类型。
//当一个函数没有返回值时,你通常会见到其返回值类型是 void:
function warnUser(): void {
console.log("这是我的警告信息。");
}
// 声明一个void类型的变量没有什么大用,因为你只能为它赋予undefined和null:
let unusable: void = undefined;
console.log(unusable)
本质:void表示“空”或“无返回值”
- 它的唯一可接受的值是undefined(在严格模式下null也不行)。
- 主要用于函数返回类型和回调函数类型。
let nothing: void = undefined;
console.log(nothing) //打印出来就是undefined
// nothing = 123; // 错误
// nothing = null; // 严格模式下错误
// nothing = undefined; // 唯一合法值
2.void的6种常见用法
1.函数返回类型:不返回任何值。
function logMessage(msg: string): void {
console.log(msg);
// 没有 return,或 return;
}
function doSomething(): void {
// 只执行操作,不返回数据
return; // 或省略 return
}
2.箭头函数作为回调时
在事件处理、定时器、数组遍历等场景中,回调函数通常不关心返回值。
3.定义回调函数类型(接口或类型别名)
当你定义一个函数,它接受一个“只执行,不返回”的回调时,用void
type Callback = () => void;
function runLater(callback: Callback) {
setTimeout(callback, 1000);
}
runLater(() => {
console.log("1秒后执行");
});
4.Promise<void>:异步操作无返回值
当一个异步操作只关心“完成”,不关心“返回什么数据”时,用Promise<void>
async function saveData(): Promise<void> {
await fetch('/api/save', { method: 'POST' });
// 只关心是否成功,不返回数据
}
// 使用:
await saveData(); // 知道它完成了,但拿不到返回值
常见于:
- 提交表单
- 保存设置
- 发送日志
5.泛型中使用void:不关心返回值。
在泛型函数或组件中,有时你想表达“返回值不重要”
function callOnce<T extends () => void>(fn: T): void {
fn();
}
callOnce(() => console.log("只执行一次"));
6.Vue/React中的时间处理器
在前端框架中,事件处理器几乎都是 void。
//vue
const handleClick = (e: MouseEvent): void => {
console.log("点击了", e);
};
//react
const Button = () => {
const handleClick = (e: React.MouseEvent): void => {
e.preventDefault();
console.log('按钮被点击');
};
return <button onClick={handleClick}>点击我</button>;
};
三、void的一个“神奇”特性:忽略返回值
TypeScript 允许返回任意值的函数赋给 () => void 类型。
const callbacks: (() => void)[] = [];
callbacks.push(() => "hello"); // 允许
callbacks.push(() => 123); // 允许
callbacks.push(() => undefined); // 允许
callbacks.forEach(fn => fn()); // 调用,但忽略返回值
四、void vs undefined vs never
- void 没有返回值 使用场景:函数返回类型、回调
- undefined JavaScript 使用场景:原始值,表示“未定义” 变量赋值、可选属性
- never 永远不会返回(如抛错、死循环) 使用场景:错误处理、穷尽性检查
<template>
<div>
<button @click="error()">click</button>
</div>
</template>
<script setup lang="ts">
function error(): never {
throw new Error("出错了");
}
function loop(): never {
while (true) {}
}
</script>
- 函数不返回值 function fn(): void
- 回调函数不关心返回值 (callback: () => void)
- 异步操作无返回数据 async fn(): Promise
- 事件处理器 (e: Event) => void
- 不要用于变量 let x: void 几乎不用
只执行,不返回
场景:
- 打印日志 不需要返回值 使用void
- 弹出提示框 不需要返回值 使用void
- 提交表单 不需要返回值 使用void
- 监听点击事件 不需要返回值 使用void
- 保存数据到本地 不需要返回值 使用void
- 查询数据 需要返回数据 不使用void
虽然 void “不返回东西”,但它做的事非常重要!
它可能:打印日志、修改数据、触发 UI 更新、发送网络请求…… 只是它不把结果传回来而已。 就像你调用 console.log(),它没返回值,但确实“做了事”。
这类请求 只关心“是否成功”,不关心“返回了什么数据”。
// 场景 1:提交、保存、删除等操作
// 用户点击“保存设置”
async function saveSettings(): Promise<void> {
await fetch('/api/save', { method: 'POST', body: data });
// 只要没报错,就认为成功了
}
// 使用:
await saveSettings(); // 成功保存,但拿不到具体数据
?场景 2:发送日志、埋点
async function trackEvent(): Promise<void> {
await fetch('/api/track', { method: 'POST', body: event });
}
但大多数请求都需要返回数据的
// 场景 1:查询用户信息 (需要数据!)
interface User {
id: number;
name: string;
email: string;
}
async function getUser(): Promise<User> {
const res = await fetch("/api/user");
return res.json();
}
// 使用:
const user = await getUser(); // 拿到 user 数据,用于显示
console.log(user.name);
// 场景 2:搜索订单列表 (需要数据!)
async function searchOrders(): Promise<Order[]> {
const res = await fetch('/api/orders');
return res.json();
}
Null和Underined
// TypeScript里,undefined和null两者各自有自己的类型分别叫做undefined和null。
// 和 void相似,它们的本身的类型用处不是很大:
// Not much else we can assign to these variables!
let u: undefined = undefined;
console.log(u)
let nn: null = null;
console.log(nn)
// 默认情况下null和undefined是所有类型的子类型。
// 就是说你可以把 null和undefined赋值给number类型的变量。
// 然而,当你指定了--strictNullChecks标记,null和undefined只能赋值给void和它们各自。
// 这能避免 很多常见的问题。 也许在某处你想传入一个 string或null或undefined,
// 你可以使用联合类型string | null | undefined。 再次说明,稍后我们会介绍联合类型。
注意:我们鼓励尽可能地使用--strictNullChecks,但在本手册里我们假设这个标记是关闭的。
Never
项目中几乎用不到never的,never”只是一个表达“永不发送”的思想,不是实际代码。
never 就像一个“永远不会回来的人”——它代表一个函数“根本不会正常结束”。 它不是返回 undefined,不是返回 null,而是:压根就不会有返回值,因为它“卡住”了,或者“出事了”。
- 场景一:
//这个函数一旦调用,就会抛错,程序可能崩溃或跳到 catch。
//所以它永远不会“正常结束” → 类型是 never。
function throwError(message: string): never {
throw new Error(message);
// ❗ 代码执行到这里就“中断”了
// 后面的代码永远不会执行
}
- 场景二:死循环(永远执行下去)
function infiniteLoop(): never {
while (true) {
console.log("永不停歇...");
}
// ❗ 循环永不结束,函数永远不会 return
}
//这个函数一旦运行,就永远不会结束。
//所以它也不会返回任何值 → 类型是 never。
- 场景三:穷尽性检查(TypeScript的“兜底警告”)
这是never最高级也最实用的用法!
enum Color {
Red,
Green,
Blue
}
function handleColor(c: Color) {
switch (c) {
case Color.Red:
console.log("红色");
break;
case Color.Green:
console.log("绿色");
break;
case Color.Blue:
console.log("蓝色");
break;
default:
// 如果未来新增了 Color.Yellow,但没处理
// 这里就会触发 error,因为 c 是 never 类型
const _exhaustiveCheck: never = c;
throw new Error(`未处理的颜色: ${c}`);
}
}
void vs never
- void 正常结束,但不返回值 (我干完活了,但没给你东西)
- never 根本不会结束,或直接出错(我不干了,或者直接不干了)
never 就是 TypeScript 里的“绝路”标志: “走到这里的代码,理论上永远不应该被执行,如果执行了,说明你出错了!”
Object
ts:接受所有对象number,string,boolean,symbol, null , undefined。
const user = { name: 'Alice' }; // object
const arr = [1, 2, 3]; // object(数组本质是对象)
const fn = () => {}; // object(函数也是对象)
const date = new Date(); // object
const regex = /abc/; // object
console.log(user)
console.log(arr)
console.log(fn)
console.log(date)
console.log(regex)
console.log(typeof { }); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"(但 TS 中函数属于 object 范畴)
console.log(typeof null); // "object"(js历史 bug!但 TS 处理了)
类型断言
类型断言(Type Assertion) 就是告诉 TypeScript 编译器:“我相信这个值的类型就是我所说的那样”,即使 TypeScript 无法自动推断出来。
它类似于其他语言中的“类型转换”(type casting),但不会在运行时改变值的类型或结构,只是在编译时告诉 TypeScript “请按这个类型处理”。
两种写法:
-
- 尖括号语法
let value: any = "Hello, TypeScript";
let len: number = (<string>value).length;
-
- as 语法 value as Type 推荐
let value: any = "Hello, TypeScript";
let len: number = (value as string).length;
关于let
你可能已经注意到了,我们使用let关键字来代替大家所熟悉的JavaScript关键字var。
let关键字是JavaScript的一个新概念,TypeScript实现了它。
我们会在以后详细介绍它,很多常见的问题都可以通过使用 let来解决,所以尽可能地使用let来代替var吧。