原始数据类型:
- boolean 布尔值
- number 数值
- string 字符串
- null 空值
- undefined 未定义
- Symbol (ES6 中的新类型)
非原始数据类型:
数组 arr: number[] arr: Array
Tuple 元祖 x: [string, number]
enum 枚举
enum Color {Red, Green, Blue}; let c: Color = Color.Blue;//默认情况下,从 0 开始为元素编号。 console.log(c); // 输出 2 enum Person { name = "NAME", age = "AGE", love = "LOVE", hobby = "HOBBY", } console.log(Person.name); // NAME console.log(Person.hobby); // HOBBY
never 永不存在的值的类型
void
//void 类型像是与 any 类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void。 function hello(): void { alert("Hello ts"); }
any 任意类型
联合类型
//联合类型(Union Types)表示取值可以为多种类型中的一种。 let num: string | number; num = "seven"; num = 7;
- 函数类型
- unknown 表示一个未知的类型,使用
unknown
标注的变量和参数必须经过类型检查和转换后才能使用。
let unde: void = undefined;
let nu: void = null;
let un: undefined = undefined;
let nu: null = null;
//与 void 的区别是,undefined是所有类型的子类型。也就是说 undefined 类型的变量,可以赋值给 number 类型的变量
let num: number = undefined;
let un: undefined;
let num2: number = un;
TypeScript支持访符 public,private 和 protected,它们决定了类成员的可访问性。
public(公共):所有定义成public的属性和方法都可以在任何地方进行访问。
private(私有):所有定义成private的属性和方法都只能在类定义内部进行访问。
protected(受保护): 该类及其子类的所有成员都可以访问它们。 但是该类的实例无法访问
//通过不同方式使用联合类型写法 |
// 方法1:
let arr1: (number | string)[] = [1]
arr1.push(1)
arr1.push('3')
// 方法2:
let arr2 : Array<string | number> = [1, '2']
arr2.push(1)
arr2.push('3')
// 方法3:
type newType = number|string
let arr3:newType []= [3]
arr3.push(1)
arr4.push('5')
接口是一系列抽象方法的声明,是一些
方法特征的集合
,这些方法都应该是抽象的,需要由具体的类去实现,然后第三方就可以通过这组抽象方法调用,让具体的类执行具体的方法。
//接口定义 interface
interface interface_name {
}
//以下实例中,我们定义了一个接口 IPerson,接着定义了一个变量 customer,它的类型是 IPerson。
//customer 实现了接口 IPerson 的属性和方法。
interface IPerson {
firstName:string,
lastName:string,
sayHi: ()=>string
}
var customer:IPerson = {
firstName:"Tom",
lastName:"Hanks",
sayHi: ():string =>{return "Hi there"}
}
console.log("Customer 对象 ") //Customer 对象
console.log(customer.firstName) //Tom
console.log(customer.lastName)//Hanks
console.log(customer.sayHi()) //Hi there
对象:对象是TS中一种数据类型,可以用来
存储多个数据属性和方法
,并且可以通过对象字面量或者构造函数来创建实例接口:接口是TS中定义
数据结构的规范
,主要用于描述对象的形状,即对象应该包含哪些属性和方法,但不提供实现。接口可以作为一个契约,确保其他代码符合其规范
//对象
let person = {
name: "Tom",
age: 18,
sayHi: function() {
console.log("Hi");
}
};
console.log(person.name); // Tom
person.sayHi(); // Hi
//接口
interface Person {
name: string;
age: number;
sayHi(): void;
}
let person: Person = {
name: "Tom",
age: 18,
sayHi() {
console.log("Hi");
}
};
console.log(person.name); // Tom
person.sayHi(); // Hi
类型别名及类型符号csdn详情参考
上述介绍了ts中的数据类型和接口,但是在开发过程中 不可避免的会遇到各种复杂类型 , 有些数据类型更灵活、复杂,那么此时,类型别名是一种非常有用的工具,它可以帮助我们简化代码,提高代码的可读性和可维护性
基本用法:
type 类型名 = 类型值
type Name = string;
type Age = number;
type Person = {
name: Name;
age: Age;
sayHi(): void;
};
let person: Person = {
name: "Tom",
age: 18,
sayHi() {
console.log("Hi");
}
};
console.log(person.name); // Tom
person.sayHi(); // Hi
字面量类型(Literal Types)用来表示具体的字面量值,包括字符串、数字、布尔值等。它们可以作为类型注解的一部分,用来限制变量、函数参数、函数返回值等的取值范围
数字字面量,字符串字面量,布尔字面量,空值字面量,枚举字面量
//数字字面量
type Num = 10
const num: Num = 10
const num2: Num = 20 // 抛错,不能将20赋值给类型10
//字符串字面量
type Str = "a"
const num: Str = "a"
//布尔字面量
type Bool = false
const bool: Bool = false
//空值字面量
type Void = void;
const isNull: Void = null
const isUndefined: Void = undefined
const isVoid: Void = void 0
//枚举字面量
enum Color {
Red = 1,
Green,
Blue
}
type colorBlue = Color.Blue
const blue: colorBlue = 3
TypeScript中的类型符号是用来声明变量类型的符号,主要有以下几种:
:
:用于声明变量的类型,例如:let a: number = 10;
表示声明一个名为a的变量,并将其类型标注为number。?
:用于表示某个属性或参数是可选的,例如:interface Person { name: string; age?: number; }
表示Person接口的age属性是可选的。[]
:用于表示数组类型,例如:let arr: number[] = [1, 2, 3];
表示声明一个名为arr的数组,其中元素类型为number。()
:用于表示函数类型,例如:function add(a: number, b: number): number { return a + b; }
表示声明一个名为add的函数,其中参数a和b的类型均为number,返回值类型也为number。|
:用于表示联合类型,例如:let c: number | boolean = 10;
表示声明一个名为c的变量,其类型为number或者boolean。&
:用于表示交叉类型,例如:interface A { a: number; } interface B { b: string; } type C = A & B;
表示定义一个名为C的交叉类型,它同时包含A和B两个接口的属性和方法
交叉类型(Intersection Types)可以用来将多个类型合并为一个类型。交叉类型使用
且符号&
进行连接两个或多个类型;值得注意的是交叉类型一般使用于对象定义这种复杂的数据类型,如果使用交叉类型定义基础类型,则会转换为never类型,因为一个类型不可能同时兼备两种基础类型
& 连接的是简单联合类型,则产生的新类型是 & 符号两边类型的公有类型。
//交叉基础类型,错误示范
type str = string
type num = number
type StrAndNum = str & num // never类型
//正确示范
type information = {
name: string
age?: number //?是可选类型,可以下放交叉不使用
}
type information2 = {
readonly address: string
}
type user = information & information2
const whiteDog: WhiteDog = {
name: "lc",
address: "中国",
}
//` & 连接的是简单联合类型
type A = string | number
type B = string[] | number
// C是A和B共有的类型,number类型
type C = A & B
泛型:使用尖括号<>来声明类型参数 (可以有多个)来表示暂时未知的类型,在实际声明变量时传入相应的类型 (或者由TS自动推论) 来替换相应出现该类型参数的地方,从而将抽象的、未知的类型替换为具体的、已知的类型。一个类型参数指代一种类型,例如
分别指代一种暂时未知的类型。将泛型用于定义对象类型,便得到了泛型对象。
// 类型T代表一种暂时未知的类型
interface PersonInfo<T> {
info: T
}
// 传入类型变量string,这时候string就会在相应的地方替换原来的T
let p1: PersonInfo<string> = {
info: 'cc'
}
let p2: PersonInfo<number> = {
info: 18
}
let p3: PersonInfo<'男' | '女'> = {
info: "男"
}
泛型同样可在类型别名中使用。而类型别名除了定义对象类型之外,还能用泛型来定义各种其它类型。因此,我们可以使用泛型嵌套来定义更为复杂的类型结构
类型断言(Type Assertion)是一种显式地告诉编译器变量的类型的方式,它允许我们手动指定一个变量的类型,从而绕过TypeScript编译器对该变量类型的检查
//断言两种方式,<>和as
let str: unknown
const len: number = (<string>str).length
let str: unknown
const len: number = (str as string).length
个人理解:事先定义了一个变量为它设置了类型,但是在其它场景需要这个变量为其它类型为了避免报错通过断言
指定它为需求类型
类型
unknown
表示一个未知的类型。与any
类型不同,使用unknown
标注的变量和参数必须经过类型检查和转换后才能使用。应用场景:
- 当我们不知道某个变量的类型时,在某些情况下可以先把它标注为
unknown
类型,并在使用前进行类型检查或类型转换。- 当我们编写一些通用的函数或库时,为了避免与不同的代码库之间发生类型冲突,可以使用
unknown
类型来定义变量和参数。
function processValue(value: unknown) {
if (typeof value === "string") {
console.log(value.toUpperCase());
} else if (typeof value === "number") {
console.log(value.toFixed(2));
}
}
let val1: unknown = "hello";
processValue(val1); // 输出HELLO
let val2: unknown = 3.1415;
processValue(val2); // 输出3.14
let val3: unknown = true;
processValue(val3); // 编译时错误:boolean类型不能转换为string或number类型
从上面的例子中可以看出,如果不进行类型检查或类型转换,使用unknown
类型的变量会导致编译时错误。但是,通过类型检查和转换,我们可以安全地使用这个变量并避免类型错误。
函数名称相同,但是参数的个数或者类型不同。
// 函数的定义
function add(num1: number, num2: number): number;
function add(num1: string, num2: string): string;
// 函数的实现
function add(num1: any, num2: any): any {
return num1 + num2;
}
通过
abstract
定义抽象类在 TypeScript 中,抽象类是一种特殊的类,它
本身不能被实例化,而只能被继承
。抽象类可以包含抽象方法(即只有方法签名,没有实现),用于定义一些基本的行为或约束子类必须实现的方法,以及普通的具体方法,用于提供一些默认的实现。
// 不可以 new Animal 只能继承抽象类
abstract class Animal {
abstract makeSound(): void;
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
class Dog extends Animal {
makeSound() {
console.log("Woof! Woof!");
}
}
let dog = new Dog();
dog.makeSound(); // "Woof! Woof!"
dog.move(10); // "Animal moved 10m."
typeof 类型守卫:使用 typeof 运算符可以判断一个变量的类型是 string、number、boolean、symbol 或 undefined。
instanceof 类型守卫:使用 instanceof 运算符可以判断一个变量是否为指定类的实例。它的使用方法是在检测对象的同时指定一个构造函数作为比较对象
//typeof
function example(value: string | number) {
if (typeof value === "string") {
console.log(`The value is a string: ${value}`);
} else {
console.log(`The value is a number: ${value}`);
}
}
example("hello"); // Output: "The value is a string: hello"
example(42); // Output: "The value is a number: 42"
//instanceof
class MyClass {}
function example(input: MyClass | string) {
if (input instanceof MyClass) {
console.log("The input is an instance of MyClass.");
} else {
console.log(`The input is a string: ${input}`);
}
}
example(new MyClass()); // Output: "The input is an instance of MyClass."
example("hello"); // Output: "The input is a string: hello"
在 TypeScript 中,编译上下文是指编译器对源代码进行类型检查和转换时所使用的环境和规则
编译上下文可以包含以下几个方面:
- 编译选项:编译器可以通过命令行参数或 tsconfig.json 文件等方式配置各种编译选项,包括输出目录、模块解析方式、生成的 JavaScript 版本等。
- 类型检查:编译器会对源代码进行类型检查,以捕获可能的类型错误和提供更准确的类型推断。类型检查过程中涉及到类型系统、类型注解、类型推断等概念。
- 类型转换:在编译过程中,TypeScript 会将源代码中使用的语言特性(如类、接口、泛型、枚举、命名空间等)转换成相应的 JavaScript 代码。这个过程中,编译器还会进行一些优化和调整。
- 声明文件处理:TypeScript 支持使用声明文件来描述 JavaScript 库和模块的类型信息,以提高与第三方库的兼容性和开发效率。编译器会自动搜索项目中的声明文件,或者对于没有声明文件的库,也可以通过第三方工具自动生成。
- 模块解析:在编译过程中,编译器需要解析模块之间的依赖关系,以便正确地生成相应的 JavaScript 代码文件。模块解析涉及到模块路径、模块别名、自定义解析等问题。
tsconfig.json 是一个用于配置 TypeScript 编译器的配置文件。通过这个配置文件,可以指定编译器所使用的规则和选项,以实现自定义编译过程和调整输出结果
{
"compilerOptions": {
/* 基本选项 */
"target": "es5", /* 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT' */
"module": "commonjs", /* 指定模块化代码生成方式: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext' */
"lib": ["es6", "dom"], /* 指定要包含在编译中的库文件,默认为所有支持的库 */
"outDir": "./dist", /* 指定输出目录 */
"rootDir": "./src", /* 指定源代码目录 */
/* 详细选项 */
"strict": true, /* 启用所有严格类型检查选项 */
"noImplicitAny": true, /* 在表达式和声明上有隐含的 any 类型时报错 */
"strictNullChecks": true, /* 启用严格的 null 检查 */
"noImplicitThis": true, /* 当 this 表达式值为 any 类型的时候,生成一个错误 */
"alwaysStrict": true, /* 以严格模式检查每个模块,并在模块内部启用 "use strict" */
/* 配置文件扩展选项 */
"resolveJsonModule": true, /* 允许导入 .json 模块 */
"esModuleInterop": true, /* 自动生成命名空间导入 (import * as module from "module") */
"skipLibCheck": true /* 跳过对声明文件的检查 */
}
}
js没有重载概念,ts有可以重载
ts增加了接口interface、泛型、类、类的多态、继承等
ts对比js基础类型上,增加了 void/never/any/元组/枚举/以及一些高级类型
选择学习
- 类型系统:TS 是一种拥有静态类型检查的编程语言,支持在代码中明确指定变量的数据类型、声明函数的输入和输出类型、定义接口和类等。而 JS 则是一种动态类型的语言,变量类型是在运行时动态确定的。
- 编译方式:TS 是一种编译型语言,需要通过编译器将 TS 代码转换为等价的 JS 代码才能在浏览器或者 Node.js 中执行。而 JS 是一种解释型语言,直接由运行时解释执行。
- 扩展语法:TS 支持 ECMAScript 标准中定义的所有语法,并且还提供了一些自己的扩展语法,例如枚举类型、泛型、元组类型等。JS 则不支持所有扩展语法,并且在新标准发布前需要等待浏览器厂商的实现或者使用 polyfill 进行补丁。
- 开发工具:TS 具备良好的 IDE 集成、语法高亮、代码提示、错误检查等功能,开发体验更加友好。JS 的开发工具则相对简单,主要是一些文本编辑器和浏览器控制台。
- 生态环境:TS 是由微软开发并维护的项目,有着全球范围内的活跃社区和丰富的第三方库。JS 则更加开放和自由,生态环境更加广泛和多样化。