定义
TypeScript 是一个开源的编程语言,通过在 JavaScript(世界上最常用的语言之一) 的基础上添加静态类型定义构建而成。
Typescript 与 JavaScript 的区别
Typescript | Javascript |
---|---|
静态语言 | 动态语言 |
一种面向对象的编程语言, 需要TypeScript编译器才能转换为JavaScript文件 | 一种脚本语言, 不需要编译器, 可以在浏览器上运行。 |
强类型, 支持静态和动态类型 | 弱类型, 没有静态类型选项 |
接口,重载等特性 | 不支持接口,同名函数会被最后定的覆盖 |
如何使用
npm install -g typescript # 安装
echo hello_world.ts > const gender: string = 'Female'; # 新建ts文件
tsc hello_world.ts # 编译成js
语法
基础类型
// 以下可以不写类型声明,ts可以类型推断
let handsome: boolean = true;
let age: number = 18;
let name: string = 'Rain120;
let travel_cities: string[] = [
'beijing',
];
// 使用数组泛型
let travel_cities2: Array<string> = [
'beijing',
];
let age: [number, string] = [18, '18']; // Tuple
enum Gender { // enum
FEMALE,
MALE,
}
let value: any; // 不会对他做任何类型检查
let value: unknown; // any 类型对应的安全类型,解决any的问题
let u: undefined = undefined;
let n: null = null;
function warnUser(): void {
console.log("This is my warning message");
}
// 字面量类型
const a = '123'
let b = '123'
let b: 123
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
高级类型
// 函数
// 函数声明
function getFullName(name?: string = 'test'): string { // 返回值可推断
return `Rainy ${name}`;
}
// 函数表达式
const getFullName: (name: string) => string = function(name: string): string {
return `Rainy ${name}`;
}
// 接口
interface Profile {
readonly name: string;
age?: string | number;
gender: 'MALE' | 'FEMALE';
new (...args: any[]) : Profile
[propName: string]: any;
}
// 交叉类型 交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型, 它包含了所需的所有类型的特性
interface Boy {
handsome: boolean;
}
interface Girl {
cute: boolean;
}
type Person = Boy & Girl;
const someone: Person = {
handsome: true,
cute: false
};
// 联合类型 联合类型具有 或 关系的多个类型组合而成, 只要满足其中一个类型即可。当你不确定某个对象的值是什么类型时就可以使用 联合类型
interface Boy {
hair: boolean;
tall: boolean;
}
interface Girl {
hair: boolean;
cute: boolean;
}
type Person2 = Boy | Girl
const someone3: Person2 = {
hair: true,
cute: true
}
类型断言
// as 用来手动指定一个值的类型(类型断言 或 类型保护)。换句话来说,就是你比编译器更了解这个变量的类型是什么
const someValue: any = "this is a string";
const strLength: number = (someValue as string).length;
const strLength: number = (<string>someValue).length;
// ! 非空断言 不包含 null 和 undefined的值
const profile: any = {
name: 'Rain120',
schools: {}
}
const getProfile(profile: any) {
console.log(profile!.name, profile!.age, profile!.schools!)
}
const curry = (fn: any) => {
return fn!();
}
进阶
类型保护
// typeof类型保护
function padLeft(value: string, padding: string | number) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}
interface Padder {
getPaddingString(): string
}
// instanceof 类型保护
class SpaceRepeatingPadder implements Padder {
constructor(private numSpaces: number) { }
getPaddingString() {
return Array(this.numSpaces + 1).join(" ");
}
}
class StringPadder implements Padder {
constructor(private value: string) { }
getPaddingString() {
return this.value;
}
}
function getRandomPadder() {
return Math.random() < 0.5 ?
new SpaceRepeatingPadder(4) :
new StringPadder(" ");
}
// 类型为SpaceRepeatingPadder | StringPadder
let padder: Padder = getRandomPadder();
if (padder instanceof SpaceRepeatingPadder) {
padder; // 类型细化为'SpaceRepeatingPadder'
}
if (padder instanceof StringPadder) {
padder; // 类型细化为'StringPadder'
}
// 用户自定义的类型保护
function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined;
}
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
let pet = {
fly() {
console.log(11)
}
}
if (isFish(pet)) {
pet.swim();
}
else {
pet.fly();
}
// 泛型
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
// 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
// keyof
interface T {
a: number;
b: string;
}
type TKeys = keyof T; // "a" | "b"
type PropAType = T['a']; // number
// 索引签名
interface Foo {
[keys: string]: string;
}
// 映射类型
// 将接口下的字段全部变为可选的
type Partial<T> = {
[K in keyof T]?: T[k];
};
// 条件类型
// T extends U ? X : Y
type TypeName<T> = T extends string
? "string"
: T extends number
? "number"
: T extends boolean
? "boolean"
: T extends undefined
? "undefined"
: T extends Function
? "function"
: "object";
// infer
// 类型系统在获得足够的信息后,就能将infer后跟随的类型参数推导出来
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
// 工具类型
type Required<T> = {
[K in keyof T]-?: T[K];
};
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
type Exclude<T, U> = T extends U ? never : T;
// K extends keyof any 约束K必须为联合类型
type Record<K extends keyof any, T> = {
[P in K]: T;
};
// 递归类型
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};