当前位置:网站首页>TypeScript手把手教程,简单易懂
TypeScript手把手教程,简单易懂
2022-07-05 08:34:00 【Thetimezipsby】
TypeScript手把手教程,简单易懂
简介
TypeScript (简称 ts)是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,它由 Microsoft 开发
超集:也就是说 typescript有javascript没有的功能用来增强javascript
准备工作
- 安装(在node环境下)
npm i -g typescript or yarn global add typescript
- 检查是否安装成功
tsc -v 注意:tsc只有安装完typescript才有
工作流
由于ts代码无法在浏览器中运行,所以编写的ts代码(Code.ts)由ts的编译器tsc进行编译代码(Code.ts)编译成功后会自动创建改ts所对应的js代码(Code.js)
JavaScript 和 TypeScript 的区别
- JavaScript:边解释边执行,错误只有在运行的时候才能发现
- TypeScript:先编译再执行,在写的时候就会发现错误了(ts不能直接执行,需要先编译成 js )
ts的好处
有利于规范我们的代码、代码编译阶段能更好的发现错误、强类型语言
入门必须
类型注解
就是给变量添加类型约束,可以显示标记出代码中的意外行为,从而降低了发生错误的可能性
格式:let 变量名: 类型 = 初始值
例:let name:string = ‘张三’
已知js原有类型:
- 原始类型:string、number、boolean、null、undefined、symbol
- 对象类型:object(包括,数组、对象、函数等对象)
ts新增类型:tuple(元组)、enum(枚举)、void、never、any、unknown、联合类型、字面量类型
用法
- 原有类型
// 字符串类型 let myName: string = '张三' // 数值类型 let age: number = 18 // 布尔类型 let isLoading: boolean = false // undefined let un: undefined = undefined // null let timer: null = null // symbol let uniKey: symbol = Symbol() //数组 let array1: number[] = [1,2,3,4,5] //or let array2: Array<number> = [1,2,3,4,5] //对象 let obj: { name:string, age:number} = { name: '张三', age: 18} //函数 let fun: (num1: number, num2: number) => number = function (num1: number, num2: number) { return num1 + num2; } console.log(fun(1, 2)); // 3 // 注意冒号后面是什么类型,值就必须是什么类型,否则编译会报相关错误 ↓ // Type 'string' is not assignable to type 'number'.
- 新增类型
tuple(元组)
它约定了的元素个数
它约定了特定索引对应的数据类型let person: [number,string] = [1, '张三']
enum(枚举)
使用枚举我们可以定义一些有名字的数字常量。枚举通过enum关键字定义。//定义一个颜色枚举类 enum Color{ red, green, blue, } //使用 let color = Color.red; console.log(color) // 0 //注意: 枚举中的对应的值默认从0开始以此类推 //修改其值 enum Color2{ red = 'red', green = 10, blue = 'blue' }
void
通常用于函数返回值,定义一个函数没有返回任何东西,可以认为返回void
可以用到void 有以下几种情况:- 函数没写return
- 只写了 return, 没有具体的返回值
- return 的是 undefined
// 如果什么都不写,此时,add 函数的返回值类型为: void const add = () => { } // 如果return之后什么都不写,此时,add 函数的返回值类型为: void const add2 = () => { return } const add3 = (): void => { // 此处,返回的 undefined 是 JS 中的一个值 return undefined } // 这种写法是明确指定函数返回值类型为 void,与上面不指定返回值类型相同 const add4 = (): void => { }
never
通常应用于函数返回值,当函数未执行完时改函数的返回值为never// 表示永远不会有返回结果 function throwError(message:string, errorCode:number): never { throw { message, errorCode } }
any
表示任意类型,对声明该any类型的变量它的值可以是任意类型let n: any; //表示该变量 n 的值可以是任意类型 n = 123; n = '123'; n = true; // ...
unknown
表示未知类型的值,也可是任意类型let n: unknown; //表示该变量 n 的值可以是任意类型 n = 123; n = '123'; n = true; // ...
拓展》》》
any、unknown 区别?
any 类型的变量可以直接赋值给其他变量
unknown 类型的变量不能直接赋值给其他变量let a:any a= 123; a= 'object' let b: string b = a // ok let c: unknown; c = 123 c = '123' let d: number; d = c // Type 'unknown' is not assignable to type 'number'.
联合类型
需求:如何定义一个变量可以是 string 也可以是 number 类型? 这个时候,前面所学的已经不能满足我们的需求了,就需要用到一个新的类型 - 联合类型。let a: number | string; // 变量a可以写两个类型 a = 123; a = '123'; a = true; // 报错 Type 'boolean' is not assignable to type 'string | number'.
注意:冒号后面的类型可以有多个 用 | 竖线分割;例如:let b: number | string | null | …;
由两个或多个其他类型组成的类型,表示可以是这些类型中的任意一种。不要和 js 中的 || 搞混哦字面量类型
在 TypeScript 中,字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型。TypeScript 支持 3 种字面量类型:字符串字面量类型、数字字面量类型、布尔字面量类型。对应的字符串字面量、数字字面量、布尔字面量分别拥有与其值一样的字面量类型。
说白了就是某个变量的类型是一个或多个固定的值就是字面量类型let str: 'hello world' = 'hello world'; // 表示该 str 值必须是 hello world let num: 996 = 996; // 表示该 num 值必须是 996 let bool: true = true; // 表示该 bool 值必须是 true //搭配联合类型使用 let age: 18 | 20 | 25 | 30; // age的值必须是 冒号后面类型其中一个 age = 18; //ok age = 60;// 报错 Type '60' is not assignable to type '18 | 20 | 25 | 30'.
类型断言
就是告诉编译器,我知道这个值是什么类型,也知道自己在干什么
格式: 1. <类型>变量名
2. 变量名 as 类型
例如:
// 返回一个数字或字符串的长度
function getString(val: string | number): number {
// 此时ts类型推导不知道val是string还是number,需要指定这个val此时的类型是string
if ((<string>val).length) {
// 使用第二种断言格式
return (val as string).length;
} else {
// 此时说明val的类型的number
return val.toString().length;
}
}
console.log(getString(123)); // 3
console.log(getString("1234")); // 4
类型别名
在我们定义类型的时候,有时候自己定义的类型名往往很长,这个时候就需要在定义个别名,方便书写。
格式:type 别名 = 类型
type s = string // 定义
const str1:s = 'abc' // 使用
const str2:string = 'abc'
作用:
- 给类型起别名
- 定义了新类型
使用场景:给复杂的类型起个别名,比如:多个联合类型
type NewType = string | number
let a: NewType = 1
let b: NewType = '1'
函数
和JavaScript一样,TypeScript函数可以创建有名字的函数、箭头函数和匿名函数还是自执行函数。 你可以随意选择适合应用程序的方式,不论是定义一系列API函数还是只使用一次的函数
// 普通函数
function 函数名(形参1: 类型=默认值, 形参2:类型=默认值,...): 返回值类型 {
}
// 声明式实际写法:
function add(num1: number, num2: number): number {
return num1 + num2
}
// 箭头函数
const 函数名(形参1: 类型=默认值, 形参2:类型=默认值, ...):返回值类型 => {
}
const add2 = (a: number =100, b: number = 100): number =>{
return a + b
}
// 注意: 箭头函数的返回值类型要写在参数小括号的后面
函数-可选参数
使用函数实现某个功能时,参数可以传也可以不传。
例如:数组的 slice 方法,可以 slice() 也可以 slice(1) 还可以 slice(1, 3) 那么就可以定义可选参数 语法:
function slice (a?: number, b?: number) {
// ? 跟在参数名字的后面,表示可选的参数
// 注意:可选参数只能在 必须参数的后面
// 如果可选参数在必选参数的前面,会报错
console.log(111);
}
slice()
slice(1)
slice(1,2)
类
与js的类相似,可以理解为对象的模板,包含属性和方法
格式: class 类名 (类名首字母大写)
class Greeter {
// 属性
greeting: string;
// 构造函数
constructor(message: string) {
this.greeting = message;
}
// 方法
greet() {
return "Hello, " + this.greeting;
}
}
//根据类的构造函数创建对象
let greeter = new Greeter("world");
类的修饰符
访问修饰符
public
声明属性和方法(默认) 在哪个地方都可以访问属性、方法class Point { public x: number; public y: number; constructor(x: number, y: number) { this.x = x; this.y = y; } public getPosition() { return `(${ this.x}, ${ this.y})`; } } const point = new Point(1, 2) console.log(point.x) // 1 console.log(point.y) // 2 console.log(point.getPosition()) // (1, 2)
private
声明属性和方法 将属性和方法私有化 外界不能访问class Parent { private age: number; constructor(age: number) { this.age = age; } } const p = new Parent(18); console.log(p); // { age: 18 } console.log(p.age); // 报错 Property 'age' is private and only accessible within class 'Parent'. console.log(Parent.age); // 报错 Property 'age' does not exist on type 'typeof Parent'. class Child extends Parent { constructor(age: number) { super(age); console.log(super.age); // Property 'age' is private and only accessible within class 'Parent' } }
protected
声明属性和方法 与private相似,区别是在继承中子可以访问父的protectedclass Parent { protected age: number; constructor(age: number) { this.age = age; } protected getAge() { return this.age; } } const p = new Parent(18); console.log(p.age); // 报错 Property 'age' is protected and only accessible within class 'Parent' and its subclasses. console.log(Parent.age); // 报错 Property 'age' does not exist on type 'typeof Parent'. class Child extends Parent { constructor(age: number) { super(age); console.log(super.getAge()); } } new Child(19)
只读修饰符
在类中可以使用readonly
关键字将属性设置为只读class UserInfo { readonly name: string; constructor(name: string) { this.name = name; } } const user = new UserInfo("TypeScript"); user.name = "haha"; // error Cannot assign to 'name' because it is a read-only property
静态修饰符
在类中可以使用static
关键字将属性或方法设置为静态类型class Parent { static age: number = 18; static getAge() { return Parent.age; } constructor() { // } } // 静态类型不用实例化对象直接用 类名. 的方式调用 console.log(Parent.age); // 18 console.log(Parent.getAge()) // 18
类的继承
与js的继承相似,通常用继承来扩展现有的类。继承之后,子类会拥有父类的一切属性和方法
格式:class 子类 extends 父类
// 创建父类
class Parent {
name: string;
constructor(name: string) {
this.name = name
}
getName() {
return this.name;
}
}
// 创建子类并继承父
class Child extends Parent {
//构造函数
constructor(childName: string) {
super(childName) // 将子类创建时传入的值 给到父构造函数
}
testFn() {
console.log(this.name)
console.log(this.getName());
}
}
const c = new Child('张三');
c.testFn();
注意点:
- 在构造函数中super()作为方法表示父类的构造函数,super作为对象时,在普通方法中,指向父类的原型对象;
- 如果在子类中写了构造函数,就必须调用父类的构造函数
存取器getters/setters
TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
class Demo {
// 私有属性外界不能访问,可以通过存取器进行控制
private _name: string;
private _age: number;
constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
get name() {
// 获取时执行
return this._name;
}
set name(val: string) {
// 修改时执行
this._name = val
}
}
const d = new Demo('a',10);
d.name = 'abc'
console.log(d.name)
注意:只带有 get不带有 set的存取器自动被推断为 readonly
接口
当一个对象类型被多次使用时,有如下两种方式来来描述对象的类型,以达到复用的目的:
- 类型别名,type
- 接口,interface
说白了也就是对对象和类进行约束限制的一种方式
格式:
interface 接口名 {属性1: 类型1, 属性2: 类型2}
// 这里用 interface 关键字来声明接口
interface IGoodItem {
// 接口名称(比如,此处的 IPerson),可以是任意合法的变量名称,推荐以 `I` 开头
name: string,
price: number,
func: ()=>string
}
// 声明接口后,直接使用接口名称作为变量的类型
const good1: IGoodItem = {
name: '手表',
price: 200,
func: function() {
return '看时间'
}
}
const good2: IGoodItem = {
name: '手机',
price: 2000,
func: function() {
return '打电话'
}
}
接口和类型 的区别 interface(接口)和 type(类型别名)的对比:
- 相同点:都可以给对象指定类型
- 不同点:
- 接口,只能为对象指定类型。它可以继承。
- 类型别名,不仅可以为对象指定类型,实际上可以为任意类型指定别名
// 接口的写法-------------
interface IPerson {
name: string,
age: number
}
const user1:IPerson = {
name: 'a',
age: 20
}
// type的写法-------------
type Person = {
name: string,
age: number
}
const user2:Person = {
name: 'b',
age: 20
}
接口继承
如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承来实现复用
格式:
interface 接口2 extends 接口1 {
属性1: 类型1, // 接口2中特有的类型
}
interface a {
x: number; y: number }
// 继承 a
// 使用 extends(继承)关键字实现了接口
interface b extends a {
z: number
}
// 继承后,b 就有了 a 的所有属性和方法(此时,b 同时有 x、y、z 三个属性)
泛型
就是当类型尚不明确时,可以用变量暂时替代,当使用时在明确指定或不指定,ts会根据值进行类型推断,通常用于类、接口和函数 (也就是为了更好的重用)
注意:泛型可以有多个或一个
泛型类
泛型应用于类上面
class Person<T>{
private _value: T;
constructor(val: T) {
this._value = val;
}
}
let p = new Person<number>(12)
如上,表示传递一个T类型,在new的时候才把具体类型传入。其中T(Type)是变量可更改,但通常比较常见就是写T,T可以理解成占位符,当进行实例化时传入类型填充此位置
泛型接口
泛型应用在接口上
interface Identities<V, M> {
value: V,
message: M
}
let ident: Identities<number,string> = {
value: 123,
message: '123'
}
泛型函数
泛型应用在函数上
function id<T, U>(arg1: T, arg2: U): T {
return arg1;
}
//调用时传入相应类型,不传ts会根据传入参数进行类型推断
console.log(id<string,number>('1',3)) // "1"
console.log(id('1',3)) // "1"
到这里就结束了,后续还会更新 vue 系列相关,还请持续关注!
感谢阅读,若有错误可以在下方评论区留言哦!!!
推荐文章
ts保姆级教程,别再说你不会ts了
你不知道的 TypeScript 泛型(万字长文,建议收藏)
接近天花板的TS类型体操,看懂你就能玩转TS了
TypeScript中的never类型具体有什么用?
理解 TypeScript 类型收窄
边栏推荐
猜你喜欢
随机推荐
DCDC circuit - function of bootstrap capacitor
Classic application of MOS transistor circuit design (1) -iic bidirectional level shift
How to write cover letter?
Reasons for the insecurity of C language standard function scanf
猜谜语啦(142)
319. 灯泡开关
猜谜语啦(11)
亿学学堂给的证券账户安不安全?哪里可以开户
go依赖注入--google开源库wire
More than 90% of hardware engineers will encounter problems when MOS tubes are burned out!
Shell script
Buildroot system for making raspberry pie cm3
One question per day - replace spaces
Stm32--- systick timer
STM32 single chip microcomputer -- volatile keyword
猜谜语啦(7)
实例003:完全平方数 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
Arrangement of some library files
MySQL之MHA高可用集群
Classic application of MOS transistor circuit design (2) - switch circuit design