TypeScript教程---------基础
Posted 神仙姥姥敲bug
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript教程---------基础相关的知识,希望对你有一定的参考价值。
TS 介绍
TS 是什么
ts 是拥有类型检查系统的 javascript 超集, 提供了对 es6 的支持, 可以编译成纯 javascript,运行在任何浏览器上。
TypeScript 编译工具可以运行在任何服务器和任何系统上。TypeScript 是开源的。
为什么要用 TS
ts 总体给我的感觉就是, 它能约束代码, 又有一定的灵活度, 可以培养你的编程习惯, 输出更高质量, 维护性高, 可读性高的代码
- 编译代码时,进行严格的静态类型检查, 编译阶段而不是运行时发现很多错误, 特别是一些很低级的错误
- 帮助我们在写代码的时候提供更丰富的语法提示, 方便的查看定义对象上的属性和方法
比如: 你给函数传了一个对象, 你在函数实现的时候还得记住对象里面都有啥参数, 你定义的参数名字是啥
TS 安装
npm init -y
npm install typescript -g
数据类型
- js 中的数据类型:
字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
对象(Object)、数组(Array)、函数(Function) - ts 包含 js 中所有的类型, 而且还新增了几种类型
void、any、never、元组、枚举、高级类型
类型注解:
(变量/函数):type
布尔类型(boolean)
let flag: boolean = true
数字类型(number)
let num: number = 8;
字符串类型(string)
let str: string = \'sxh\';
- 数组类型(array)
let arr1:number[]=[1,2,3] let arr2:Array<number>=[1,2,3]
只读数组 数组创建后不能被修改
let ro: ReadonlyArray<number> = arr1; // arr1.push(3); // ro[1] = 4; // ro.push(6); // ro.length = 100; // arr1 = ro; // let arr3: number[] = ro
元组类型(tuple)
控制了数组成员的类型和数量let tuple:[string,number]=[\'sxh\',10] //元祖越界问题: tuple.push(2)//可以添加的类型是所有数组成员的联合类型 console.log(tuple[2])//不能这样访问
枚举类型(enum)
普通枚举
若枚举类型未指定值或指定的值为number类型, 可对其进行双向取值// 双向取值 enum Color { RED, BLUE, } console.log(Color[0], Color[1]); console.log(Color[\'RED\'], Color[\'BLUE\']); enum Color { RED=2, BLUE, } enum ActionType { ADD = \'ADD\', EDIT = \'EDIT\', DELETE = \'DELETE\', }
常量枚举
const enum Status { \'success\', \'warning\', \'fail\', } let loginStatus = [Status.success, Status.warning, Status.fail];
keyof typeof Enum, 将枚举类型转换为联合类型
enum ActionType { ADD, EDIT, DELETE, } type ActionTypeConst = keyof typeof ActionType // \'ADD\' | \'EDIT\' | \'DELETE\'
null、undefined
null, undefined 是其他类型的子类型, 可以赋值给其他类型的变量
strictNullChecks 为 true 的话不能赋值给其他类型let str: string; str = null; str = undefined;
- 任意类型(any)
任意类型 any 类型 类型转换困难的时候, 数据类型结构复杂,没有类型声明的时候用
如果变量定义为 any 类型, 跟 js 差不多了, 不进行类型检查了 unkonwn 未知类型
let a: any let b: unkonwn a.toFixed() b.toFixed()
void 无类型
常用于没有具体返回值的函数const handler = (param: string):void => {}
never 类型
永远不存在的值
任何类型的字类型, 可以赋值给任何类型
但是任何类型都不可赋值给 never, 包括 anyfunction error(msg: string): never { throw new Error(\'我报错了\'); // 直接异常结束了 } function loop(): never { while (true) {} } function fn(x: number | string) { if (typeof x === \'number\') { // 类型保护 console.log(x); } else if (typeof x === \'string\') { console.log(x); } else { console.log(x); } }
类型推论
如果没有指定类型, TS 会根据类型推论推断出一个类型.
如果变量定义的时候没有赋值, 默认是 any 类型
let x; // 可以赋值为任何类型的值
let x1 = \'生生世世\'; // x1会推论成sring类型, 不能给x1赋值为其他类型了
// x1 = 222;
如果 TS 能正确推断出其类型, 我们可采用类型推论而不必定义类型
function sum(x: number, y: number){
return x + y;
}
联合类型
let name1: string | number;
// console.log(name1.toFixed());
// console.log(name1.toString());
name1 = 3;
name1 = \'sxh\';
类型断言
类型断言用来告诉编译器 “我知道自己在干什么”, 有 尖括号 和 as 两种写法. 在 tsx 语法中, 只支持 as.
let name1: string = \'111\'
let name2: string | number;
// console.log(name2.toFixed())
console.log((name2 as number).toFixed());
// 双重断言
console.log((name1 as any) as boolean);
字符串字面量类型
//字符串字面量
const left: \'left\' = \'left\';
const right: \'right\' = \'right\';
type pos = \'left\' | \'right\';
function loc(pos: pos) {}
// loc(\'up\')
// 类型字面量
type Person = {
name: string;
age: number;
};
let p1: Person = {
name: \'sxh\',
age: 18,
};
字符串字面量 vs 联合类型
type T1 = \'1\' | \'2\' | \'3\';
type T2 = string | number | boolean;
let t1: T1 = \'2\';
let t2: T2 = true;
函数
函数定义
定义函数有两种方式: 1. 函数定义 2.函数表达式
// 1.直接声明
function person2(name: string): void {
console.log(name);
}
person2(\'sxh\');
// 2.变量声明
let sum: (x:number, y:number) => number
sum = (a,b)=>a+b
sum(1,2)
// 3.类型别名
type Sum = (a: number, b: number) => void;
let sum: Sum = function (a: number, b: number): number {
return a + b;
};
let sum2: Sum = function (a: number, b: number): void {// 没有返回值
// return a + b;
};
const myAdd = (x: number, y: number) => x + y; // 也可以直接这样定义, 类型会自动推导
// 4.接口
interface Sum{
(x:number, y: number):number
}
let sum: Sum = (a,b)=>a+b
sum(1,2)
可选参数
必须放在最后一个参数位置
function sum3(a: number, b: number, c?: number) {}
sum3(1, 2);
// 设置默认值, 最后一个参数设置默认值就, 函数调用可传可不传, 相当于可选参数
function sum4(a: number, b: number, c = 6) {
return a + b + c;
}
sum4(1, 2);
// 第一个参数设置默认值, 使用默认调用的时候必须传 undefiend
function sum5(a = 3, b: number) {
return a + b;
}
console.log(sum5(undefined, 2));
剩余参数
function sum6(...args: number[]) {
return args.reduce((val, item) => val + item, 0);
}
sum6(1, 2, 3, 5);
函数的重载
给同一个函数提供多个函数定义
let catOpt: any = {};
function cat(param: string): void;
function cat(param: number): void;
function cat(param: any) {
if (typeof param === \'string\') {
catOpt.name = param;
} else if (typeof param === \'number\') {
catOpt.age = param;
}
}
cat(\'小花\');
cat(3);
function add(a: string, b: number): void;
function add(a: number, b: number): void;
function add(a: string | number, b: string | number): void {}
add(1, 2);
// add(1, \'2\');
类
如何定义类
class Book {
name: string;
getName(): void {
console.log(this.name);
}
}
let book1 = new Book();
book1.name = \'ts\';
book1.getName();
存取器
通过存取器来改变一个类中属性的读取和赋值行为
class MyBook {
bname: string; // 属性
constructor(bname: string) {
this.bname = bname;
}
get name() {
return this.bname;
}
set name(value) {
this.bname = value;
}
}
let myBook = new MyBook(\'ts\');
myBook.name = \'js\';
console.log(myBook.name);
参数属性
class MyBook1 {
// bname: string;
constructor(public bname: string) {
// this.bname = bname;
}
get name() {
return this.bname;
}
set name(value) {
this.bname = value;
}
}
let myBook1 = new MyBook1(\'ts\');
myBook1.name = \'js\';
console.log(myBook1.name);
readonly
class MyBook2 {
readonly bname: string; // 公开的只读属性只能在声明时或者构造函数中赋值
readonly num: number = 1;
constructor(bname: string) {
this.bname = name;
}
changeName(value) {
// this.bname = value;
}
}
继承
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat(food: string) {
console.log(\'吃什么\', food);
}
}
class Cat extends Animal {
color: string;
constructor(name: string, color: string) {
super(name);
this.color = color;
}
}
let cat = new Cat(\'哈哈\', \'white\');
console.log(cat.name);
cat.eat(\'fish\');
类里面的修饰符
public 公有属性, private私有属性, protected受保护的
// public 公有属性 , ts默认为public
class Animal1 {
public name: string; // 自己, 子类和实例都可以访问
private age: number = 2; // 自己可以访问, 子类 和 实例 都不可以访问,
protected body: string; // 自己和子类可以访问, 实例不可以访问
public constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public eat(food: string) {
console.log(\'吃什么\', food);
}
private getAge() {
return this.age;
}
}
class Dog extends Animal1 {
color: string;
constructor(name: string, age: number, color: string) {
super(name, age);
this.color = color;
}
dogInfo() {
// console.log(this.name);
// console.log(this.body);
// console.log(this.age);
}
}
let an = new Animal1(\'哈哈\', 2);
let dog = new Dog(\'哈哈\', 2, \'white\');
console.log(dog.name);
// console.log(dog.age);
// console.log(dog.body);
// console.log(dog.getAge());
静态属性 静态方法
类自身上的属性和方法
class Button {
static type = \'link\';
static getType() {
return Button.type;
}
public content: string;
constructor(content: string) {
this.content = content;
}
}
console.log(Button.getType);
console.log(Button.type);
class SubButton extends Button {}
let btn = new SubButton(\'ok\');
SubButton.type = \'e\';
console.log(Button.type);
console.log(SubButton.type);
抽象类
是抽象概念, 不能被实例化
abstract class Input {
label: string;
abstract changeValue(): void; // 此方法在子类中必须得实现
}
class SearchInput extends Input {
changeValue() {} // 必须得实现抽象类里抽象方法
}
抽象方法 不包含具体实现, 必须在子类中实现
有关键字 abstract
接口
描述对象的形状
interface Cats { // 多属性和少属性都不行
name: string;
text?: string; // 可选属性
speak(): void;
}
let Cat: Cats = {
name: \'sxh\',
speak() {},
};
行为的抽象
同名接口可以写多个, 类型会自动合并
interface Plus {
add(): void;
}
interface Minus {
minus(): void;
}
class Compute implements Plus, Minus {
//使用接口约束类
add() {}
minus() {}
}
任意属性
interface Book {
readonly id: number;
name: string;
// [key: string]: any;
}
let b: Book = {
id: 1,
name: \'sxh\',
// age: 18,
};
以上是关于TypeScript教程---------基础的主要内容,如果未能解决你的问题,请参考以下文章