一、TypeScript 是什么
TypeScript 是一种由微软开发的自由和开源的编程语言。于2012年推出。
TypeScript 是 JavaScript 的一个超集。为 JavaScript 添加了类型系统。
使用 tsc -h 命令查看帮助文档
tsc -h
3. 编译 TypeScript 文件
tsc hello.ts
tsc hello.ts --outfile a.js
tsc hello.ts --outdir dist
典型 TypeScript 工作流程
TypeScript 初体验
function greet(person: string) {
return Hello ${name}
}
console.log(greet(“TypeScript”));
执行 tsc hello.ts 命令,之后会生成一个编译好的文件 hello.js
function greet(person) {
return "Hello ".concat(name);
}
console.log(greet(“TypeScript”));
类型擦除:粗略地说,一旦 TypeScript 的编译器完成了对代码的检查,它就会擦除类型来生成“编译”的代码。 这意味着一旦你的代码被编译,生成的纯JS代码就没有类型信息。
二、基元类型:String、Number、Boolean
类型注解 :string 或者 : string(有无空格不影响)
注意:类型定义好后不能修改
let str1: string = “hello”;
str1 = “world”; // ok
str1 = 123; // error
Hello ${firstName}, age is ${age}
;通常希望避免这种情况,因为未进行类型检查。这时可以 noImplicitAny 配置
let value1: unknown = value; // ok
let value2: any = value; // ok
let value3: number = value; // Error
let value4: string = value; // Error
对 unknown 类型的值做一些操作时,这些操作将不再被认为是类型正确的。
// 声明一个 unknown 类型的变量
let notSure: unknown = 4;
// 可以给它赋值为 其他任何类型
notSure = “maybe it is a string”;
notSure = true;
// 不同于 any, 读取任意属性或方法都会报类型错误,避免运行时的错误问题
str3.split(0,1); //error
str3.length; // error
// 调用它不存在的属性or方法
notSure.myName; // Error
notSure.getName(); // Error
// 将它赋值给任意类型
let num: number = notSure; // Error
Any & Unknown ⭐
共同点:
foo = bar; // Error: 不能将 ‘string’ 赋值给 number
六、函数
函数是在 JavaScript 中传递数据的主要方式。 TypeScript 允许您指定函数的输入和输出值的类型。
greet(“hello”); // OK
greet(42); // Error 类型“number”的参数不能赋给类型“string”的参数。
2. 可选参数
/**
greet(“hello”); // OK
greet(); // OK
greet(42); // Error 类型“number”的参数不能赋给类型“string”的参数
3. 返回类型标注
函数没有标注返回值类型,默认的返回值类型是 void
function getFavoriteNumber(): number {
// return 26; // OK
return “hello”; // Error 不能将类型“string”分配给类型“number”。
}
4. 匿名函数自动推断类型
const names = [“Alice”, “Bob”, “Eve”];
names.forEach(function (s) {
console.log(s.toUppercase()); // Error 属性“toUppercase”在类型“string”上不存在。你是否指的是“toUpperCase”?
});
names.forEach((s) => {
console.log(s.toUppercase()); // Error 属性“toUppercase”在类型“string”上不存在。你是否指的是“toUpperCase”?
});
5. 参数默认值设置
function fn1(name: string = “张三”, age?: number){}
七、对象类型
要定义对象类型,我们只需列出其属性及其类型
// key 的分割可以是,也可以是;(推荐使用;)
function printCoord(pt: { x: number; y: number }) {
console.log("The coordinate’s x value is " + pt.x);
console.log("The coordinate’s y value is " + pt.y);
}
printCoord({ x: 3, y: 7 }); // OK
printCoord({ x: “3”, y: “8” }); // Error 不能将类型“string”分配给类型“number”
printName({ first: “Bob” }); // OK
printName({ first: “Alice”, last: “Alisson” }); // OK
2. 可选属性检查
当您从可选属性读取时,您必须在使用之前进行检查。
function printName(obj: { first: string; last?: string }) {
console.log(obj.last.toUpperCase()); // Error 对象可能为“未定义”
if (obj.last !== undefined) {
// OK
console.log(obj.last.toUpperCase());
}
// OK
console.log(obj.last?.toUpperCase());
}
类型缩窄
// 1. 直接使用 ?. 可选链语法
person.age?.toFixed();
// 2. 类型缩窄 if
if(person.age){
person.age.toFixed();
}
// 3. 类型缩窄 &&
person.age && person.age.toFixed();
// 4. 类型缩窄 三元运算
person.age ? person.age.toFixed() : undefined;
3. 只读属性
对象类型还可以指定其部分或全部属性是只读的。只需要在属性名称前添加 readonly 即可。
function printName(obj: { readonly first: string; last?: string }) {
obj.first = “hello”; // Error 无法分配到 “first” ,因为它是只读属性。
}
八、联合类型
联合类型是由两个或多个其他类型组成的类型,通常使用 | 联合。
printId(100); // OK
printId(“200”); // OK
printId(true); // Error 类型“boolean”的参数不能赋给类型“string | number”的参数
let isOk: 0 | 1 = 2; // 不能将类型“2”分配给类型“0 | 1”
2. 使用联合类型
在 TypeScript 中,若一个变量使用了联合类型,那么当我们使用该变量时必不可少的会去明确的限制该变量的具体类型,这称为类型缩小。
function printId(id: number | string) {
console.log(id.toUpperCase()); // Error
// 类型缩小
if (typeof id === “string”) {
// In this branch, id is of type ‘string’
console.log(id.toUpperCase());
} else {
// Here, id is of type ‘number’
console.log(id);
}
}
九、类型别名 type
将现有的一些类型取个别名,方便后续复用。
function printCoord(pt: Point) {
console.log("The coordinate’s x value is " + pt.x);
console.log("The coordinate’s y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });
2. 描述函数
type SetPoint = (x: number, y: number) => void;
3. 描述联合类型
type ID = number | string;
十、接口 interface
接口声明是命名对象类型的另一种方法
interface 的名字,一般推荐以大写 8I 开头
function printCoord(pt: Point) {
console.log("The coordinate’s x value is " + pt.x);
console.log("The coordinate’s y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });
2. 描述函数
interface SetPoint {
(x: number, y: number): void;
}
十一、type 和 interface ⭐
// 多个拓展 写法
type Dog = {
sex: 0 | 1;
}
type Bear = Animal & Dog & {
honey: boolean;
}
interface Dog2 {
sex: 0 | 1;
}
interface Bear extends Animal, Dog2 {
honey: boolean;
}
2. 不同点
类型别名可以为基本类型、联合类型或元组类型定义别名,而接口不行。
同名接口会自动合并,而类型别名不会。
使用场景
使用类型别名的场景:
a. 定义基本类型的别名时,使用 type
b. 定义元组类型时,使用 type
c. 定义函数类型时,使用 type
d. 定义联合类型时,使用 type
e. 定义映射类型时,使用 type
使用接口的场景:
a. 需要利用接口自动合并特性的时候,使用 interface
b. 定义对象类型且无需使用 type 的时候,使用 interface
十二、TypeScript 断言
类型断言
有时候你会遇到这样的情况,你会比 TypeScript 更了解某个值的详细信息。通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方法可以告诉编译器,”相信我,我知道自己在干什么“。类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和解构。它没有运行时的影响,只是在编译阶段起作用。
类型断言有两种方式:
console.log(str);
console.log(str1);
}
2. 调用函数时忽略 undefined 类型
type CallbackType = () => number;
function myFunc(callback: CallbackType | undefined) {
const num1 = callback(); // Error 不能调用可能是“未定义”的对象。
const num2 = callback!(); // Ok
}
十三、文本类型
除了一般类型之外,我们还可以在类型位置引用特定的字符串和数字
let isOk: 0 | 1 = 2; // 不能将类型“2”分配给类型“0 | 1”
let string: “hello” = “”; // Error 不能将类型““””分配给类型““hello””
十四、Null 和 Undefined 类型
TypeScript 中,undefined 和 null 两者都有各自的类型分别为 undefined 和 null。
let u: undefined = undefined;
let n: null = null;
十五、Enum 类型(枚举)
使用枚举我们可以定义一些带名字的常量。使用枚举可以清晰地表达意图或创建一组有区别的用例。
TypeScript 支持数字和字符串的枚举。
let dir: Direction = Direction.Up;
/**
let dir: Direction = Direction.Up;
/**
let dirName = Direction[0]; // Up
let dirValue = Direction.Up; // 0
3. 常量枚举
除了数字枚举和字符串枚举之外,还有一种特殊的枚举 – 常量枚举。它是使用 const 关键字修饰的枚举,常量枚举会使用内联语法,不会为枚举类型编译生产任何 JavaScript 。
const enum Direction {
Up,
Down,
Left,
Right,
}
let dir: Direction = Direction.Up;
编译生成的 JS 代码如下:
var dir = 0 /* Direction.Up */;
4. 异构枚举
异构枚举的成员值是数字和字符串的混合
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = “YES”,
}
十六、 Void 类型 与 Never 类型
Hello ${name}
);// 但当你主动返回 undefined 时,返回值类型为 undefined
function world(name: string) {
console.log(Hello ${name}
);
return undefined;
}
2. Never 类型
never 类型表示的是那些永不存在的类型。
// 返回 never 的函数必须存在无法达到的终点
function error(message: string): never {
// 1. 通过抛出异常实现 返回值类型为 never
throw new Error(message);
}
function infiniteLoop(): never {
// 2. 通过死循环实现 返回值类型为 never
while (true) {}
}
// 类型别名 a 是一个 never 类型。因为不存在一个类型既是 string 又是 number
type a = string & number