一.类型别名的使用
type NumType = number;
let num: NumType = 23;
//这里使用了联合类型,同时HeType是类型别名
type HeType = number | string | object;
let heVal=23;
// num3?可选
type numsType = { num1: number, num2: number, num3?: number }
function sum(nums: numsType) {
console.log(nums.num1, nums.num2, nums.num3)
}
sum({ num1: 1, num2: 3 })
二.接口的声明
type numsType = {
num1: number,
num2: number,
num3?: number
}
//类型别名和接口非常相似,在定义对象类型时,大部分时候,你可以任意选择使用。
// 接口interface
//声明的方式
interface newType{
num1: number,
num2: number,
num3?: number
}
function ceshi(nums:newType){
console.log(nums.num1,nums.num2,nums.num3)
}
ceshi({num1:34,num2:1,num3:8})
两者区别
- type类型使用范围更广接口类型;只能用来声明对象;可以使用联合、交叉等复杂类型
- 在声明对象时,interface 可以多次声明;可以被合并
interface newType{
num1: number,
num2: number,
num3?: number
}
interface newType{
num4: number
}
function ceshi(nums:newType){
console.log(nums.num1,nums.num2,nums.num3)
}
ceshi({num1:34,num2:1,num3:8,num4:4})
- interface 继承:
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
const square: Square = {
color: "red",
sideLength: 10
};
- interface被类实现:用于描述类应该具有的成员。当一个类实现了一个接口时,它必须实现该接口中定义的所有成员。
interface Animal {
name: string;
makeSound(): void;
}
class Dog implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound() {
console.log("Woof!");
}
}
const dog = new Dog("Buddy");
dog.makeSound(); // 输出 "Woof!"
三.交叉类型
允许你将多个类型合并为一个类型。通过使用 & 运算符,你可以将多个类型组合在一起,从而创建一个新的类型,该类型包含了所有类型的成员
interface Person {
name: string;
age: number;
}
interface Employee {
id: number;
department: ()=>void;
}
type EmployeePerson = Person & Employee;
const employeePerson: EmployeePerson = {
name: "Alice",
age: 30,
id: 123,
department: ()=>{
console.log("employeePerson")
}
};
四.字面量类型
字面量类型是 TypeScript 中一种特殊的类型,它表示一个具体的值。字面量类型可以是字符串、数字、布尔值或者符号。
在 TypeScript 中,你可以使用字面量类型来限制变量的取值范围,使其只能取特定的值。这有助于提高代码的可读性和可靠性。
1.字符串字面量类型:
let color: "red" | "green" | "blue";
color = "red"; // 合法
color = "yellow"; // 错误,因为 "yellow" 不是允许的值
//常用于封装请求的请求方式限制
2.数字字面量类型:
let number: 1 | 2 | 3;
number = 1; // 合法
number = 4; // 错误,因为 4 不是允许的值
3.布尔字面量类型:
let truth: true | false;
truth = true; // 合法
truth = false; // 合法
truth = 0; // 错误,因为 0 不是允许的值
通过使用字面量类型,你可以明确地指定一个变量只能取特定的值,从而在编译时捕获潜在的错误。这在一些特定的情况下非常有用,例如定义枚举类型、状态标识等
五.类型断言as
类型断言是一种方式,用于告诉编译器一个值的类型。当你比编译器更清楚某个值的类型时,可以使用类型断言来覆盖 TypeScript 的类型推断。as 关键字是类型断言的一种方式。
有两种形式的类型断言:
1.尖括号语法:
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
2. as 语法:
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
两种语法的效果相同,都是将 someValue 断言为 string 类型,以便获取其 length 属性。在实际使用中,as 语法更为常见,因为它不会与 JSX 的语法冲突。
注意:类型断言不会在运行时进行类型检查或转换。它们只是在编译阶段告诉编译器将一个值视为特定的类型。因此,如果类型断言不正确,可能会导致运行时错误。因此,要谨慎使用类型断言,最好是避免在不确定的情况下使用它们。
六.非空类型断言!
非空断言使用的是!,表示可以确定某个标识符是有值的,跳过 ts 在编译阶段对它的检测
let someValue: string | null = "hello";
let strLength: number = someValue!.length; // 使用非空类型断言告诉编译器,someValue 不会为 null
七.类型缩小
通过一些操作或条件判断来缩小变量的类型范围,使得在后续代码中 TypeScript 能够更准确地推断变量的类型。
1. typeof 类型保护:
function printAll(strs: string | string[] | null) {
if (typeof strs === "object") {
for (const s of strs) { // strs 的类型被缩小为 string[]
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs); // strs 的类型被缩小为 string
}
}
2.平等缩小
对变量进行相等性检查,以缩小其类型范围的方法
let x: string | number = "hello";
if (x === "hello") {
// 在这里,x 被缩小为 string 类型
console.log(x.toUpperCase());
} else {
// 在这里,x 被缩小为 number 类型
console.log(x.toFixed(2));
}
3. instanceof 类型保护:
class Animal {}
class Dog extends Animal {
bark() {}
}
function makeSound(animal: Animal) {
if (animal instanceof Dog) {
animal.bark(); // animal 的类型被缩小为 Dog
}
}
4. in 操作符类型保护:
Javascript 有一个运算符,用于确定对象是否具有带名称的属性:in运算符
如果指定的属性在指定的对象或其原型链中,则in 运算符返回true;
interface Circle {
radius: number;
}
interface Square {
sideLength: number;
}
function getArea(shape: Circle | Square): number {
if ("radius" in shape) {
return Math.PI * shape.radius ** 2; // shape 的类型被缩小为 Circle
} else {
return shape.sideLength ** 2; // shape 的类型被缩小为 Square
}
}
八.函数类型
- 在JavaScript开发中,函数是重要的组成部分,并且函数可以
作为一等公民(可以作为参数,也可以作为返回值进行传递)。 - 那么在使用函数的过程中,函数是否也可以有自己的类型呢?
- 可以编写
函数类型的表达式(Function Type Expressions),来表示函数类型;
1. 函数表达式:
通过将函数赋值给一个变量来定义函数类型。
```
// 格式:(参数列表)=>返回值
type SubtractType = (x: number, y: number) => number
let subtract: SubtractType = function (x: number, y: number): number {
return x - y;
};
```
subtract 变量的类型也是 (x: number, y: number) => number。
2.接口定义函数类型
使用接口来定义函数类型
interface Calculator {
(x: number, y: number): number;
}
let divide: Calculator = function(x: number, y: number): number {
return x / y;
};
Calculator 接口定义了一个函数类型,然后将 divide 变量声明为 Calculator 类型。
3.函数调用签名
描述一带有属性的函数,可以在一个对象里类型中写一个调用签名
// 函数类型表达式
type oldType = (x: number, y: number) => number'
// 函数调用签名(从对象的角度来看待这个函数,也可以有其他属性)
interface NewType{
name:string,
age:number
(num31:number):number
}
const foo:NewType=(num1:number):number=>{
return 234
}
foo.name="1231"
foo.age=34
foo(234)
开发中如何选择:
- 如果只是描述函数类型本身(函数可以被调用),使用函数类型表达式(Function Type Expressions)
- 如果在描述函数作为对象可以被调用,同时也有其他属性时,使用函数调用签名(Call·signatures)
4.函数可选参数
- 可选参数:类型是number|undefined联合类型
function foo(x: number, y?: number) {
if (y !== undefined) {
// 这里使用到了类型缩小
console.log(y + 10)
}
}
foo(10);//如果上文没有?:number会进行报错提示
foo(10, 20)
- 参数默认值:
- 有默认值的情况下,参数的类型注解可以省略;
- 有默认值的参数,是可以接收一个 undefined的值
//同样可以认为联合类型
function foo(x: number, y = 100) {
console.log(y + 10)
}
foo(10);
foo(10, 20)