目录
- TS的优点和缺点
- 基础类型
- 数字类型
- 布尔类型
- 字符串类型
- void 类型
- null 类型和 undefined 类型
- bigint类型
- Symbol类型
- 其他类型
- 数组
- 元组
- 枚举Enum
- 对象和函数
- any void never unknown 的区别是什么
- 泛型 Generic
- 交叉类型
- 联合类型
- 特殊符号 ? ?. ?? ! _
- 修饰符
TS的优点和缺点
优点
-
静态类型
-
有类型错误,编译时就报错(而非运行时)
-
智能提示,提高开发效率和稳定性
缺点 -
有一定学习成本
-
某些情况下,类型定以过于混乱,可读性不好
基础类型
- boolean
- number
- string
- void
- null
- undefined
- bigint
- symbol
变量声明语法:冒号 : 前面是变量名称,后面是变量类型。
数字类型
const n:number = 100
布尔类型
const b:boolean = false;
const b2:boolean = Boolean(0);
字符串类型
let str:string = 'hello';
void 类型
当一个函数没有返回值时,可以将其返回值类型定义为 void:
function doNothing(): void {
let a = 10
}
null 类型和 undefined 类型
const a:undefined = undefined;
const b:null = null;
bigint类型
JavaScript 中可以用 Number 表示的最大整数为 2^53 - 1,可以写为 Number.MAX_SAFE_INTEGER。如果超过了这个界限,可以用 BigInt来表示,它可以表示任意大的整数。
语法:在一个整数字面量后加 n 的方式定义一个 BigInt,如:10n 或者调用函数 BigInt():
const theBiggestInt: bigint = 9007199254740991n
const alsoHuge: bigint = BigInt(9007199254740991)
const hugeString: bigint = BigInt("9007199254740991")
theBiggestInt === alsoHuge // true
theBiggestInt === hugeString // true
Symbol类型
Symbol() 函数会返回 symbol 类型的值。每个从 Symbol() 返回的 symbol 值都是唯一
的。
const sym1: symbol = Symbol()
const sym2: symbol = Symbol('foo')
const sym3: symbol = Symbol('foo')
console.log(sym2 === sym3) // false
其他类型
数组
let arr:number[] = [1,2,3];
let strs:string[] = ['点','关注'];
const list:Array<number> = [1,2,3];
元组
相同类型元素组成成为数组,不同类型元素组成了元组(Tuple)。
const list: [string, number] = ['Sherlock', 1887] // ok
const list1: [string, number] = [1887, 'Sherlock'] // error
枚举Enum
一组相同主题的数据
enum Direction { Up, Down, Left, Right }
enum Months { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec }
enum Size { big = '大', medium = '中', small = '小' }
enum Agency { province = 1, city = 2, district = 3 }
声明一个枚举类型,如果没有赋值,它们的值默认为数字类型且从 0 开始累加
enum Months {
Jan,
Feb,
Mar,
Apr
}
Months.Jan === 0 // true
Months.Feb === 1 // true
Months.Mar === 2 // true
Months.Apr === 3 // true
现实中月份是从 1 月开始的,那么只需要这样:
// 从第一个数字赋值,往后依次累加
enum Months {
Jan = 1,
Feb,
Mar,
Apr
}
Months.Jan === 1 // true
Months.Feb === 2 // true
Months.Mar === 3 // true
Months.Apr === 4 // true
枚举类型的值为字符串类型:
enum TokenType {
ACCESS = 'accessToken',
REFRESH = 'refreshToken'
}
// 两种不同的取值写法
console.log(TokenType.ACCESS === 'accessToken') // true
console.log(TokenType['REFRESH'] === 'refreshToken') // true
枚举的取值,有 TokenType.ACCESS 和 TokenType[‘ACCESS’] 这两种不同的写法,效果是相同的。
不可枚举:不可枚举是一个汉语成语,拼音为bù kě méi jǔ,意思是不能够一个个地列举,形容数量、种类极多。这个成语出自元王恽《秋涧全集·紫山先生易直解序》,其中提到“其至公正之大论,卓异特达之举,固不可枚举。”它形容的是数量非常多,多到无法计算的情况。
对象和函数
interface User {
name:string,
age:number,
sayHi:(a:string) =>string;
}
const user:User = {
name:'江拥',
age:18,
sayHi(a:string){
return a;
};
}
any void never unknown 的区别是什么
-
any 任意类型,和JS一样不进行任何类型检查,比较危险
-
void: 和any相反,没有类型, 一般应用于函数返回值
function f(): void {} //意思是这个函数没有返回值 -
never:永远不存在的类型
-
unknown:未知的类型(更加安全的any)
const b:unknown = 100;
(b as string).length //as 手动类型转换。相当于告诉TS编译器:我知道b的类型,我对安全负责
泛型 Generic
泛型是指在定义函数、接口或者类时,未指定其参数类型,只有在运行时传入才能确定。那么此时的参数类型就是一个变量,通常用大写字母 T 来表示,当然你也可以使用其他字符,如:U、K等。
//定义在函数
function fn<T>(arg:T):T{
return arg;
}
const x = fn<number>(100);
function fn2<T,U>(a:T,b:U){
console.log(a,b);
}
fn2<string,number>('x',18);
//定义在class
class someClass<T>{
name:T,
constructor(name:T){
this.name = name;
}
getName():T{
trtuen this.name;
}
}
const s1 = new someClass<string>('江拥');
const s2 = new someClass<number>(10000);
//定义在Type (不常用)
const mf:<U>(arg:U) => U = fn;
//定义在interface
interface GenericIdentityFn {
<T>(arg: T): T
}
function identity<T>(arg: T): T {
return arg
}
let myIdentity: GenericIdentityFn = identity
交叉类型
联合类型
特殊符号 ? ?. ?? ! _
//? 可选
interface User {
name:string
age?:number
}
const u:User = { name:'江拥' }
function fn(a:number,b?:number){
console.log(a,b)
}
fn(10)
// ?. 可选链
const user:any = {
info:{
city: '北京'
}
}
const city = user?.info?.city;
// ?? 空值合并运算符
//只有左侧是null或undefined,才会返回右侧
const user1:any = {
name:'江拥',
index:0
}
const n1 = user1.name ?? '暂无姓名'; //相当于const n1 = user1.name || '暂无姓名';
const n2 = user1.index ?? '暂无index';
//! 非空断言
function fn1(a?:string){
return a!.length //!表示告诉TS自己知道a不会是undefined
}
//_ 下划线 数字分隔符
const giveme= 1_000_000; //就是1000000 一百万
修饰符
在 TypeScript 中,有以下几种修饰符用于控制类的成员的访问权限:
-
public:公共修饰符,默认修饰符,可以在类的内部和外部访问。
-
private:私有修饰符,只能在类的内部访问,不能在类的外部访问。
-
protected:受保护修饰符,可以在类的内部和子类中访问,但不能在类的外部访问。
-
readonly:只读修饰符,只能在声明时或构造函数内部赋值,之后不可修改。
class Person {
public name: string;
private age: number;
protected gender: string;
readonly id: number;
constructor(name: string, age: number, gender: string, id: number) {
this.name = name;
this.age = age;
this.gender = gender;
this.id = id;
Person.count++;
}
public sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
private getAge() {
return this.age;
}
protected getGender() {
return this.gender;
}
}
class Student extends Person {
public school: string;
constructor(name: string, age: number, gender: string, id: number, school: string) {
super(name, age, gender, id);
this.school = school;
}
public introduce() {
console.log(`I am a student. My name is ${this.name}, and I study at ${this.school}.`);
}
}
let person = new Person("Alice", 25, "female", 123);
console.log(person.name); // 可以访问 public 成员
person.sayHello(); // 可以访问 public 方法
// console.log(person.age); // 不能访问 private 成员
// console.log(person.gender); // 不能访问 protected 成员
console.log(person.id); // 可以访问 readonly 成员
console.log(Person.count); // 可以直接访问静态成员
console.log(Person.getCount());
let student = new Student("Bob", 20, "male", 456, "XYZ School");
console.log(student.name); // 可以访问从父类继承的 public 成员
console.log(student.school); // 可以访问子类的 public 成员
student.introduce(); // 可以调用子类的方法
本篇是TS基础用法,日常工作够用,下一篇整理其它高阶用法