Ts | Js |
JavaScript 的超集,用于解决大型项目的代码复杂性 | 一种脚本语言,用于创建动态网页。 |
强类型,支持静态和动态类型 | 动态弱类型语言 |
可以在编译期间发现并纠正错误 | 只能在运行时发现错误 |
不允许改变变量的数据类型 | 变量可以被赋予不同类型的值 |
类型:boolean,number,string,undefined,null,any,unknown,void,never
any,unknown区别
any
:any
类型表示任意类型,它可以绕过 TypeScript 的类型检查。当你把一个值指定为 any
类型时,TypeScript 不会对这个值进行类型检查,你可以对它执行任何操作,就像在 JavaScript 中一样。unknown
:unknown
同样代表任意类型,但它是一种更安全的“任意类型”。和 any
不同,TypeScript 会对 unknown
类型的值进行类型检查,在使用 unknown
类型的值之前,你必须先对其进行类型断言或者类型缩小,否则不能对它进行操作。any
:可以将任意类型的值赋给 any
类型的变量,同时 any
类型的变量也能赋值给任意其他类型的变量。unknown
:可以把任意类型的值赋给 unknown
类型的变量,但 unknown
类型的变量不能直接赋值给其他类型的变量,除非进行类型断言或者类型缩小。let value: any = "hello";
value.toUpperCase(); // 不会报错
value.foo(); // 不会报错,即使该方法不存在
let value: unknown = "hello";
// value.toUpperCase(); // 报错
if (typeof value === 'string') {
value.toUpperCase(); // 类型缩小后,不会报错
}
any
:可以对 any
类型的值进行任意操作,TypeScript 不会进行类型检查。unknown
:在没有进行类型断言或者类型缩小之前,不能对 unknown
类型的值进行任何操作。定义数组类型
// 数组类型
let numbers: number[] = [1, 2, 3];
// 另一种数组类型定义方式,使用泛型
let strings: Array = ["a", "b", "c"];
// 元组类型,元组可以包含不同类型的值,但是元素数量和类型是固定的
let person: [string, number] = ["John", 30];
函数重载
函数重载是指两个函数名称相同,但是参数个数或参数类型不同,他的好处显而易见,不需要把相似功能的函数拆分成多个函数名称不同的函数。
不同函数类型
function add(x: number[]): number
function add(x: string[]): string
function add(x: any[]): any {
if (typeof x[0] === 'string') {
return x.join()
}
if (typeof x[0] === 'number') {
return x.reduce((acc, cur) => acc + cur)
}
}
复制代码
不同参数个数
function add(x: number[]): number
function add(x: string[]): string
function add(x: number[], y: number[]): number
function add(x: string[], y: string[]): string
function add(x: any[], y?: any[]): any {
if (Array.isArray(y) && typeof y[0] === 'number') {
return x.reduce((acc, cur) => acc + cur) + y.reduce((acc, cur) => acc + cur)
}
if (Array.isArray(y) && typeof y[0] === 'string') {
return x.join() + ',' + y.join()
}
if (typeof x[0] === 'string') {
return x.join()
}
if (typeof x[0] === 'number') {
return x.reduce((acc, cur) => acc + cur)
}
}
console.log(add([1,2,3])) // 6
console.log(add(['lin', '18'])) // 'lin,18'
console.log(add([1,2,3], [1,2,3])) // 12
console.log(add(['lin', '18'], ['man', 'handsome'])) // 'lin,18,man,handsome'
复制代码
interface
interface
(接口) 是 TS 设计出来用于定义对象类型的,可以对对象的形状进行描述。定义 interface 一般首字母大写。
interface Person {
name?: string//可选
age: number
readonly id:number//只读不可改
}
const p1: Person = {
name: 'lin',
age: 18
}
ts修饰符
TS 通过 public
、private
、protected
三个修饰符来增强了 JS 中的类。
public
修饰符public
修饰符表示公共的,使用该修饰符的类成员可以在类的内部、类的实例以及子类中被访问。在 TypeScript 中,如果不指定修饰符,类的成员默认就是 public
的。private
修饰符private
修饰符表示私有的,使用该修饰符的类成员只能在类的内部被访问,不能在类的外部或者子类中直接访问。protected
修饰符protected
修饰符表示受保护的,使用该修饰符的类成员可以在类的内部以及子类中被访问,但不能在类的外部直接访问。static
是静态属性,可以理解为是类上的一些常量,实例不能访问。type和interface区别
type:借助 type
关键字来定义,能表示各种类型,像基本类型、联合类型、交叉类型、元组类型等。
&
)来实现扩展。// 基本类型别名
type MyString = string;
// 联合类型
type StringOrNumber = string | number;
// 交叉类型
type PersonInfo = { name: string } & { age: number };
// 元组类型
type Coordinate = [number, number];
interface:使用 interface
关键字定义,主要用于定义对象类型的结构。
extends
关键字扩展,能同时扩展多个接口。interface Person {
name: string;
age: number;
}
通常用interface定义对象是因为
interface
支持声明合并,这意味着可以在不同地方多次定义同一个接口,TypeScript 会自动将这些定义合并成一个接口。
interface
使用 extends
关键字来实现继承,并且类可以使用 implements
关键字来实现接口,这种语法更加直观和清晰,符合面向对象编程的概念。
在面向对象编程中,接口通常用于描述类的契约,即类需要实现的方法和属性。
类型断言
它能够在编译阶段告知编译器某个变量的具体类型,从而绕过类型检查,让开发者能更灵活地处理类型。
尖括号语法和as语法
泛型
泛型是指在定义函数、接口或类的时候,不预先指定具体类型,而是在使用的时候再指定类型。
function identity(arg: T): T {
return arg;
}
// 使用泛型函数
let output1 = identity("myString");
let output2 = identity(100);
是泛型类型变量,它可以代表任意类型。当调用 identity
函数时,你可以指定具体的类型(如 string
或 number
)来替换 T
。arg: T
表示函数的参数 arg
的类型是 T
,return arg;
表明返回值的类型也是 T
。使用泛型,可以在定义函数、接口或类的时候,不预先指定具体类型,而是在使用的时候再指定类型。
在不使用泛型的函数中,参数类型为 any
,这意味着可以传入任何类型的值,代码的可读性和类型安全性都较差。而使用泛型的函数,通过泛型类型参数 T
明确了函数处理的是某种特定类型的值,提高了代码的可读性和可维护性。