TypeScript
使用 TypeScript
1、安装命名
npm install typescript -g
2、使用vscode 快速运行ts文件
第一步
npm install ts-node -g
第二步
安裝插件 Code Runner
第三步
npm init -y
基础类型:String、Number、Boolean、Null、Undefined,ES6 的 Symbol 和 ES10 的 BigInt
// 字符串
let str: string = 'yjt'; // yjt
// 数字
let num: number = 123; // 123
// 布尔
let booleans: boolean = true
// null 和 undefined
let u: undefined = undefined;//定义undefined
let n: null = null;//定义null
// 空值 void
function voidFn(): void {
console.log('test void')
}
Any 类型 和 unknown 顶级类型
// Any:没有强制限定哪种类型,随时切换类型都可以 我们可以对 any 进行任何操作,不需要检查类型
let any1: any = 'hhh'
any1 = 111
any1 = true
// unknown:TypeScript 3.0中引入的 unknown 类型也被认为是 top type ,但它更安全。
// 与 any 一样,所有类型都可以分配给unknown
// unknow类型比any更加严格当你要使用any 的时候可以尝试使用unknow
//unknown 可以定义任何类型的值
// let value: unknown;
// value = true; // OK
// value = 42; // OK
// value = "Hello World"; // OK
// value = []; // OK
// value = {}; // OK
// value = null; // OK
// value = undefined; // OK
//这样写会报错unknow类型不能作为子类型只能作为父类型 any可以作为父类型和子类型
//unknown类型不能赋值给其他类型
let names1: unknown = '123'
let names2: string = names2 // NO
//这样就没问题 any类型是可以的
let names3: any = '123'
let names4: string = names3 // OK
//unknown可赋值对象只有unknown 和 any
let bbb: unknown = '123'
let aaa: any = '456'
接口和对象类型
// 在typescript中,我们定义对象的方式要用关键字interface(接口),
// 我的理解是使用interface来定义一种约束,让数据的结构满足约束的格式。
// 定义方式如下
//这样写是会报错的 因为我们在person定义了a,b但是对象里面缺少b属性
//使用接口约束的时候不能多一个属性也不能少一个属性
//必须与接口保持一致
interface Person {
b: string,
a: string
}
const person: Person = {
a: "213"
}
//重名interface 可以合并
interface A { name: string }
interface A { age: number }
var x: A = { name: 'xx', age: 20 }
//继承
interface A {
name: string
}
interface B extends A {
age: number
}
let obj: B = {
age: 18,
name: "string"
}
// 可选属性 ?
//可选属性的含义是该属性可以不存在
//所以说这样写也是没问题的
interface Person1 {
b?: string,
a: string
}
const person1: Person1 = {
a: "213"
}
// 任意属性 [propName: string]
//在这个例子当中我们看到接口中并没有定义C但是并没有报错
//应为我们定义了[propName: string]: any;
//允许添加新的任意属性
interface Person2 {
b?: string,
a: string,
[propName: string]: any;
}
const person2: Person2 = {
a: "213",
c: "123"
}
// 只读属性 readonly
//这样写是会报错的
//应为a是只读的不允许重新赋值
interface Person3 {
b?: string,
readonly a: string,
[propName: string]: any;
}
const person3: Person3 = {
a: "213",
c: "123"
}
person3.a = 123 // 无法赋值
// 添加函数
interface Person4 {
b?: string,
readonly a: string,
[propName: string]: any;
cb(): void
}
const person4: Person4 = {
a: "213",
c: "123",
cb: () => {
console.log(123)
}
}
数组
1、类型加中括号
// 类型加中括号
let arr: number[] = [123]
// 这样会报错定义了数字类型出现字符串是不允许的
let arr1: number[] = [1, 2, 3, '1']
// 操作方法添加也是不允许的
let arr2: number[] = [1, 2, 3,]
arr.unshift('1')
var arr3: number[] = [1, 2, 3]; //数字类型的数组
var arr4: string[] = ["1", "2"]; //字符串类型的数组
var arr5: any[] = [1, "2", true]; //任意类型的数组
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
//表示:只要索引的类型是数字时,那么值的类型必须是数字。
2、数组泛型
// 数组泛型
let arr6: Array<number> = [1, 2, 3, 4, 5]
3、 用接口表示数组
// 用接口表示数组
interface NumberArray {
[index: number]: number;
}
4、多维数组
// 多维数组
let data: number[][] = [[1, 2], [3, 4]];
元组(数组的变种)
元组(Tuple)是固定数量的不同类型的元素的组合。
元组与集合的不同之处在于,元组中的元素类型可以是不同的,而且数量固定。
元组的好处在于可以把多个元素作为一个单元传递。
如果一个方法需要返回多个值,可以把这多个值作为元组返回,而不需要创建额外的类来表示。
1、基本使用
let arr: [number, string] = [1, 'string']
let arr2: readonly [number, boolean, string, undefined] = [1, true, 'sring', undefined]
函数的类型
1、基本使用
//注意,参数不能多传,也不能少传 必须按照约定的类型来
const fn = (name: string, age: number): string => {
return name + age
}
fn('张三', 18)
2、函数参数的默认值
// 函数参数的默认值
const fn1 = (name: string = "我是默认值"): string => {
return name
}
fn1()
3、接口定义函数
// 接口定义函数
//定义参数 num 和 num2 :后面定义返回值的类型
interface Add {
(num: number, num2: number): number
}
const fn2: Add = (num: number, num2: number): number => {
return num + num2
}
fn2(5, 5)
interface User {
name: string;
age: number;
}
function getUserInfo(user: User): User {
return user
}
联合类型 类型断言 交叉类型
1、联合类型
联合类型
let myPhone: number | string = '010'
// 函数使用联合类型
const fn = (something: number | boolean): boolean => {
return !!something
}
fn(true)
2、类型断言
interface A {
run: string
}
interface B {
build: string
}
const fn = (type: A | B): string => {
//可以使用类型断言来推断他传入的是A接口的值
return (type as A).run
}
// 类型断言是不具影响力的
function toBoolean(something: any): boolean {
return something as boolean;
}
toBoolean(1); // 返回值为 1
3、交叉类型
// interface People {
// age: number,
// height: number
// }
// interface Man {
// sex: string
// }
// const xiaoman = (man: People & Man) => {
// console.log(man.age)
// console.log(man.height)
// console.log(man.sex)
// }
// xiaoman({ age: 18, height: 180, sex: 'male' });
class 类
1、基本使用
class Person {
// 类的修饰符
// public 默认值
// private 代表定义的变量私有的只能在内部访问 不能在外部访问
// protected 代表定义的变量私有的只能在内部和继承的子类中访问 不能在外部访问
// static 静态属性 和 静态方法
// 静态属性 static 定义的属性 不可以通过this 去访问 只能通过类名去调用
// 静态方法 同样也是不能通过this 去调用 也是通过类名去调用
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
fn() {
console.log(this.name + '打飞机');
}
}
let person = new Person('yjt', 18)
person.fn()
2、nterface 定义类
// interface 定义类
interface PersonClass {
get(type: boolean): boolean
}
interface PersonClass2 {
set(): void,
asd: string
}
class A {
name: string
constructor() {
this.name = 'yjt'
}
}
// interface 定义类 使用关键字 implements 后面跟interface的名字多个用逗号隔开 继承还是用extends
class Person1 extends A implements PersonClass, PersonClass2 {
asd: string
constructor() {
super()
this.asd = '123'
}
get(type: boolean) {
return type
}
set(): void {
}
}
3、抽象类
/ 我们在A类定义了 getName 抽象方法但未实现
// 我们B类实现了A定义的抽象方法 如不实现就不报错 我们定义的抽象方法必须在派生类实现
abstract class A {
name: string
constructor(name: string) {
this.name = name;
}
print(): string {
return this.name
}
abstract getName(): string
}
class B extends A {
constructor() {
super('yjt')
}
getName(): string {
return this.name
}
}
let b = new B();
console.log(b.getName());