携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
什么是TypeScript? 为什么要用TS
TypeScript 是添加了类型系统的 JavaScript,适用于任何规模的项目。
TypeScript 是一门静态类型、强类型的语言。
TypeScript 是完全兼容 JavaScript 的,它不会修改 JavaScript 运行时的特性。
TypeScript 可以编译为 JavaScript,然后运行在浏览器、Node.js 等任何能运行 JavaScript 的环境中。
TypeScript 拥有很多编译选项,类型检查的严格程度由你决定。
TypeScript 可以和 JavaScript 共存,这意味着 JavaScript 项目能够渐进式的迁移到 TypeScript。
TypeScript 增强了编辑器(IDE,vscode)的功能,提供了代码补全、接口提示、跳转到定义、代码重构等能力。
TypeScript 拥有活跃的社区,大多数常用的第三方库都提供了类型声明。
TypeScript 与标准同步发展,符合最新的 ECMAScript 标准。
数据类型
1.基本数据类型
let 变量名: 数据类型 = 值
// 数据类型定义
let num:number = 100; // number/string/undefined/null
let str:string = 'hello'
let flag:boolean = true;
let timer:undefined = undefined;
let obj:null = null;
//字符串模板仍旧能用
const str:string=`${name}`
//申明变量的类型,但没有初始值,变量值会设置为 undefined:
//var [变量名] : [类型];
var test: string;
//申明变量并初始值,但不设置类型,该变量能够是任意类型:
//var [变量名] = 值;
var uname = "abc";
//申明变量没有设置类型和初始值,类型能够是任意类型,默认初始值为 undefined:
//var [变量名];
var cord;
默认情况下null和undefined是所有类型的子类型 ; 就是说你可以把 null和undefined赋值给任何类型的变量
2.任意类型(使用 any 关键字 定义任意类型)
let 变量名:any = value; // 后期可以随便进行更改
例子 let str:any=100; //100
3.函数的定义方式
- 函数的参数类型定义
function f(str:string, ...){
}
function fn(str:number){
console.log(fn);
}
fn(100)
- 函数返回值的定义
// 函数存在返回值
function 函数名(参数名:参数类型):返回值的类型{
return value; // value 比如符合你定义的类型
}
function sum(a:number,b:number):number{
return a+b;
}
console.log(sum(1,2));//3
// 函数没有返回值 使用void 关键字
function 函数名(参数名:参数类型):void{
// 函数不需要返回值
}
function red(a,d):void{
console.log(a);
}
red(100,200)
// 如果函数的返回值是一个对象
function f(n:string, a:number):{name:string,age:number}{
return {name:n, age:a}
}
function f(n:string, a:number):{name:string,age:number}{
return {name:n, age:a}
}
console.log(f("hello",100));//{ name: 'hello', age: 100 }
4.类型推论(没有明确的指定类型的时候推测出一个类型)
let x = 100; // 这种情况下 ts 就会使用类型推论
如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查
5.联合类型(取值可以为多种类型中的一种。 使用 | 符号)
let 变量名: 数据类型1 | 数据类型2 | ... = value ;// value 可以是 类型的任意一个; 后期可以更改为定义的类型中任意一个
let test:number | boolean // 表示test这个变量可以是number,也可以是boolean类型
let obj : {a:1} | {b:2} // 表示obj这个变量可以是{a:1},也可以是{b:2},也可以两个都有
6.交叉类型(一个变量满足被&连接的所有类型)
let obj : {name:string} & {age : number} & {age : 13}
obj = {name : '', age : 13} // 这里的age属性只能是number且值为13
7.交叉联合类型
|和 & 的混合使用,只需要记住 &优先|
对象的类型-接口
//定义了一个接口 Person,接口名字首字母大写
interface Person {
name: string;
age: number;
}
//接着定义了一个变量 tom,它的类型是 Person
let tom: Person = {
name: 'Tom',
age: 25
};
console.log(tom.name);//Tom
1. 可选属性(定义可选属性 通过 ? :)
如果有一些属性是可有可无,可以定义为可选属性,通过 在属性名后边添加 ? 实现
interface Person{
name:string;
age:number;
sex?:string;
hariColor?:string
}
let stu:Person = {
name:'hello',
age:18,
sex:'nv',
hariColor:'123984'
}
console.log(stu);
2.定义任意属性(也是可有可无)
[propName:数据类型] :any 使用 [propName: string] 定义了任意属性取 string 类型的值。
interface Person {
name: string;
age?: number;//可选属性
[propName: string]: any;//任意类型
}
let tom: Person = {
name: 'Tom',
gender: 'male'//可以是任意类型
};
3.定义只读属性(通过 readonly 关键字)
只读: 只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候:
interface Person {
readonly name:string;
age:number
}
//只读 在该环节生效的
let stu1:Person = {
name:'张三',
age:19
}
//console.log(stu.name);
stu1.name="李四"//只读属性不允许修改
函数返回值 ,返回值是对象
interface Person {
name: string;
age: number
}
//函数返回值 ,返回值是对象
function Stu1(a:Person):{name:string, age:number}{
}
数组类型
1.「类型 + 方括号」表示法
let arr:number[] = [1,2,3]
// 表示arr类型是一个数组,且数组的每一个元素都是number类型
2.元组:限定数组中每个元素的类型,同时也限定了数组中元素的个数;
元组不是数组,只是刚好符合数组的规范
let arr:[number | boolean | string] = [1,2,true,'hello',2,3,false];
// 表示arr这个数组类型中的元素类型,可以是number或者boolean
3.通过 数组的泛型 Array<数据类型>
let arr:Array<string> = ['ajds','add']
// 表示arr类型是一个数组,且数组的每一个元素都是string类型
4.通过接口定义数组 [index:number] 限定的是数组索引值的类型, 后边是限定数组中元素的类型
interface a{
// [index:number]:number
[index:number]:string
}
// let arr5:a = [1,4,5,6]
let arr5:a = ['234', '345', '35432']
允许数组中出现任意值:any[]
let arr6:any[] = [23, '345', {name:'zadf'}]
函数的类型
函数声明式
function fun(a:number, b:number){ }
函数表达式
let fun2 = function(a:number, b:number){ }
// 限定返回值
function fun(a:number):number{//第二个number就是限定的返回值(也叫输出)
return a + 100;
}
console.log(fun(100)); //200
书写函数的完整格式
// 针对的是函数表达式的方式
// 定义函数时的变量名可以不同,但是数据类型必须一致
// 区分 => 和 es6 的箭头函数 箭头 number这里是规定输出值的类型,不是箭头函数
let fun2:(x:number, y:number) => number = function(a:number, b:number):number{
return a + b; //返回值类型
}
console.log(fun2(10,20));//30
注意:箭头函数右边的number是输出类型, 右边括号外的number是返回值类型
1.可选参数
function f(x?:number){}
2.默认值参数
function f(x:number, y = 100 ){}
3.剩余参数 (不确定参数个数: 这个时候可以使用剩余参数 (rest参数))
必要参数,默认参数和可选参数有个共同点:它们表示某一个参数。 有时,你想同时操作多个参数,或者你并不知道会有多少参数传递进来。 在JavaScript里,你可以使用 arguments对象来访问所有传入的参数。
function sum(a, b){
console.log(arguments)
return a + b;
}
console.log(sum(1, 2));
function sum(a, ...rest){
console.log(rest)
return a;
}
sum(1, 2, 3, 4);
function fun(a:number, b:number, ...args:number[]){
console.log(a, b, args); //1 3 [ 4, 6, 8 ]
}
fun(1, 3, 4, 6, 8)
枚举enum
可以定义一些带名字的常量。 可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。
// 枚举
enum Gender{
Male,
Female
}
let i: {name: string, gender: Gender.Male};
i = {
name: '猴子',
gender: Gender.Male
}
console.log(i.gender === Gender.Male); //true
//字符串枚举
enum Language{
java="J",
node="N",
php="P",
python="PY"
}
console.log(Language)//{ java: 'J', node: 'N', php: 'P', python: 'PY' }
// 数字枚举-默认增长
enum Language{
html,
node,
js,
python
}
console.log(Language)
// 输入后果
{
'0': 'html',
'1': 'node',
'2': 'js',
'3': 'python',
html: 0,
node: 1,
js: 2,
python: 3
}
//数字枚举-自定义增长
enum Language{
html=6,
node,
js,
python
}
console.log(Language)
// 输入后果
{
'6': 'html',
'7': 'node',
'8': 'js',
'9': 'python',
html: 6,
node: 7,
js: 8,
python: 9
}
泛型
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型
泛型: <自定义的的值> 代表数据类型,后期由你传入的类型决定 比如: <T> <M> <A>
function f<M>(arg:M):M{
//第一个m是泛型 第二个是传入值的类型 第三个是返回值类型
return arg;
}
console.log(f<string>('hello'));//hello
类型断言(Type Assertion)可以用来手动指定一个值的类型
语法: 值 as 类型
// 接口约束 类型断言
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
// 类型断言 : 我知道自己在干嘛,所以不需要ts帮我们进行类型判断
function getName(animal: Cat | Fish) {
//return animal.name;//HEISE
// animal.run();报错
//animal.swim();报错
// 类型断言 (我知道自己要去用Fish接口)
(animal as Fish).swim()
}
let str = getName({
name: 'HEISE', swim: function () {
console.log("函数")
}
})
console.log(str);//函数
泛型约束
// 泛型约束
//在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:
function test<T>(a: T[]):T{
console.log(a.length);
// return a.length; // 报错: 泛型约束(因为这个时候你还不知道返回值是什么类型)
return a[2]
}
console.log(
test<number>([1,3,54,6]));// 4 54
类
定义类的同时,相当于定义了同名称的接口;
类可以通过关键字implements实现一个接口,从而达到遵循这个接口的规则的作用
class Person {
// 在类中,定义属性前,应该先声明这个属性的类型,也可以给这个属性设置默认值
myName : string = '无心';
constructor(name:string) {
this.myName = name
},
getName() {
return this.myName
})
}
以上这个Person类,相当于下面这个接口
interface Person {
myName : string,
getName : () => string
}