TypeScript
基础语法格式
let 属性名:属性类型 = 属性值
当你需要将某个变量 设置为 某个长度的定值,就可以需要 使用readonly
(js里面已经有)number、string、boolean、undefined、null、symbol、bigint,
(ts独特的)any、unknown、never、void
(ts独特的)object,tuple(相当于readonly)enum
类型声明建议'
string 和 String 的区别:
string 是基本数据类型(原始类型 ),String 属于 Object 类型(包装类型)。ts 官方推荐使用 string,不推荐使用 String。因为 String 耗费内存,另外代码写起来比较冗余
比如:小string,的"abc",你是没办法调用 length方法的,但是大String 是有属性的,可以调用length,但是底层,你用小string调用length 也不会报错,因为底层会自动隐式转换。
Number 和 number ,大字母灵活,兼容性好,大字母可以兼容小字母,小字母不能兼容大字母
自定义类型
-
type
-
interface
type str = string;
let a : str = "jak";
any类型(当你没有指定类型和值)
let userId: any;
// 该变量可以接收任何类型的数据
userId = 110;
userId = '110';
也就是说 ,就倒退回去,可以接收任何类型,any的意思就是任意,你没有指定,就是any
let price;
// 声明时没有指定类型,也没有赋值,类型是any
price = '10.2';
price = 3.1;
这个关于赋值,谨慎去使用,因为any类型的数据,可以赋值给严格类型,会导致混乱
let username: any;
username = 'jack';
let a: number;
// 这里的赋值居然没有报错
a = username;
console.log(a); // 而且这里的输出结果是 jack
unknown类型
unkown 可以理解为一个类型安全的 any,适用于:它将来是一个具体的类型,但是声明变量的时候还不确定类型时使用它
let a: unknown;
// 以下赋值均正常
a = 'hello';
a = 1;
a = false;
// 设置b的类型是string
let b: string;
b = a; // 报错:不能将类型“unknown”分配给类型“string”。
断言的使用 as string,就是as 确保什么类型
// 这个代码的意思是:程序员告诉TypeScript编译器,我可以保证这个 x 是string类型,你放心接收吧。
// 如果运行时,x 的类型不是string,会报错。
let x: unknown;
x = "hello";
let y: string = x as string; // 断言第一种写法
let z: string = <string>x; // 断言第二种写法
never的类型,不能定义变量
**never** 类型表示那些永远不会存在的值。undefined、null、''、0 都不行。
如果一个函数永远不会正常返回 (即永远不会到达函数末尾并返回值),那么它的返回类型应该被标注为 never。这是 never 类型最典型的用法之一
比如:
//抛出错误的函数
function throwError(message: string): never {
throw new Error(message);
// 这里不会执行任何后续代码
}
//无限循环的函数
function infiniteLoop(): never {
while (true) {
console.log("This will run forever");
}
// 永远不会退出循环,也就不会返回
}
never和void的区别
为什么用 never 而不是 void?
void 表示函数正常执行完毕但没有返回值
never 表示函数永远不会正常执行完毕
// 返回 void 的例子
function logMessage(msg: string): void {
console.log(msg);
// 函数正常结束,只是没有返回值
}
// 返回 never 的例子
function crash(): never {
throw new Error("Boom!");
// 函数不会正常结束
}
void的类型,函数的返回值没有
//void 表示一个函数正常执行结束的时候不返回任何值。如果一个函数可以正常执行结束,但最终不返回任何值时,函数在声明时建议加上 void,加上 void 之后,如果写代码的时候有返回值的操作,编译器会报错。
function sayHello(username: string): void{
console.log(`hello ${username}`);
}
但是 也允许几种情况
1.可以写return,但是不给值;
2.也可以return undefine;
3.就是不写return;
void和undefine的区别
function myFun1(): void{
console.log('myFun1执行了');
}
let result1 = myFun1();
// 这里报错了:因为编译器检测到result1变量中并不会保存具体的值
if(result1){
}
function myFun2(): undefined{
console.log('myFun2执行了');
}
let result2 = myFun2();
// 这里就没有事儿,因为result2变量中一定有值
if(result2){
}
当一个函数的返回值类型设置为 **void**和设置为 **undefined**有什么本质上的区别?
-
如果返回值类型设置为 void 表示这个方法结束的时候不返回任何值。
-
如果返回值类型设置为 undefined 表示这个方法结束的时候必须返回 undefined 值。
object 和 大Object
object是非原始类型,7 种原始类型的值无法赋值给 object 类型的变量。除了原始类型之外,其它类型都可以赋值给 object 类型,object 类型比较宽泛,不够精确,因此实际开发中较少使用。
比如:小object
let a: object;
// 以下均可赋值
a = {}; //对象
a = { name: 'jack'}; //对象
a = [1, 2, 3, 4];//数组
a = function(){} // 函数
a = new String('jack');//String
class User{} //类型
a = new User(); //对象
// 以下均报错
a = 1; //数字
a = undefined;。//未定义
a = 'hello';//字符串
a = null;//null
a = true;//boolean
比如大Object
//ts 中除了这个小 object之外,还有大 Object类型,大 Object类型的变量可以接收:凡是可以调用 Object 方法的数据。因此 Object 更加宽泛
let a: Object;
// 以下均可赋值
a = {};
a = { name: 'jack'};
a = [1, 2, 3, 4];
a = function(){}
a = new String('jack');
class User{}
a = new User();
// 这些也可以了(这几个之所以可以是因为底层会进行自动装箱,装箱之后就可以调用Object的方法了),但是小object就不行
a = 1; //数字
a = 'hello';//字符串
a = true;//boolean
// 这两个不行了,但是小object也不行
a = undefined;
a = null;
区别:大object 可以,但是小object就不行
// 这些也可以了(这几个之所以可以是因为底层会进行自动装箱,装箱之后就可以调用Object的方法了),但是小object就不行
a = 1; //数字
a = 'hello';//字符串
a = true;//boolean
声明对象类型
// 声明变量person,person变量只能接收{name: string, age: number}类型的对象。
let person: {name: string, age: number};
//使用分号 ;也可以
let person: {name: string; age: number};
// 换行
let person: {
name: string
age: number
};
// 正确
person = {
name: 'jack',
age: 20
};
// 报错
person = {
name: 'lucy'
};
// 报错
person = 1;
自定义对象类型的时候,如果某个属性不是必须的,可以使用以下语法:
let person: { name: string, age?: number };
//就是加一个问号 : ? ? ? ,就代表着 可有可无
索引签名语法
允许定义对象可以具有任意数量的属性,这些属性的键和类型是可变的,常用于:描述类型不确定的属性,具有动态属性的对象
let person: {
name: string
age?: number
// 不一定写成key,其它的也可以
// 表示该属性的属性名是一个字符串,该属性的值可以是任何类型
[key: string]: any,
// 表示该属性的属性名是一个数字,该属性的值可以是string或number
[key: number]: string | number
};
person = {
name: 'jackson',
age: 20,
gender: '男',
address: '北京海淀',
1: "jackson@123.com"
};
声明函数类型
// 自定义函数类型
// 注意:以下这个箭头不是箭头函数。是一种ts自定义函数类型的一种语法。
// 语法格式:(参数名1:类型, 参数名2:类型, .....) => 返回值类型
let myFunction: (x: number, y: number) => number;
// 给变量myFunction赋值一个函数
myFunction = function(a: number, b: number): number{
return a + b;
}
// 因为自定义函数类型的时候已经指定了参数的类型以及返回值的类型,因此可以简写为:
myFunction = function(a, b){
return a + b;
}
// 赋值的时候也可以使用js中的箭头函数
// 这里的箭头表示:箭头函数。
myFunction = (k, f) => k + f;
声明数组类型
// 字符串数组
let arr1: string[];
arr1 = ['jack', 'lucy', 'tom'];
// 数字数组
let arr2: number[];
arr2 = [1, 2, 3, 4, 5];
// 字符串数组
// 也可以采用泛型语法,后面再说泛型。
let arr3: Array<string>;
arr3 = ['cat', 'dog', 'fish'];
元组
let arr1: [string, number];
let arr2: [string, number?];
let arr3: [number, ...string[]];
arr3 = [20, 'a', 'b', 'c', 'd', 'e', 'f'];
枚举 enum
enum UserStatus {
//如果不指定值,那就是从0开始
Active = 1,
Disabled = 2,
Deleted = 3
}
let status: UserStatus = UserStatus.Active;
// 枚举名字的命名方式一般遵循大驼峰命名方式。
enum UserStatus {
//如果不指定值,那就是从0开始
Active,
Disabled,
Deleted
}
可以通过描述 和 反向 来获取
enum UserStatus {
Active,
Disabled = 20,
Deleted
}
console.log(UserStatus[0]);
console.log(UserStatus[20]);
console.log(UserStatus[21]);
//或者这样
console.log(UserStatus.Active);
console.log(UserStatus.Disabled);
console.log(UserStatus.Deleted);
但是 字符串枚举,是没有反向映射的
enum UserStatus {
Active = '激活',
Disabled = '失效',
Deleted = '已删除'
}
console.log(UserStatus.Active);
console.log(UserStatus.Disabled);
console.log(UserStatus.Deleted);
交叉类型
1.使用 &
2.比如A 类型 和 B类型,要重合的去选,
3,A = 123
4.B = 124
那么结果要是1234
函数类型
type A = () => void;
特殊情况:用这种表示类型,有一个特殊情况,这样可以有返回值
let log = function () {
return 1;
}
定义类 和继承类(跟java一样)
简写语法
属性
constructor( name:string,age:number,public salary :number){
super(name.age)
}