1.学习TypeScript1(环境安装/基础类型)

学习资料

以下以是视频徐老师笔记,感谢徐老师的课程,有需要学习ts的同学,可以去上面连接看看徐老师的视频,都是干货,通俗易懂,无费话。

安装环境

安装typescript

% npm install typescript -g
% tsc -v
Version 5.5.4

新建项目目录

mkdir demo
cd demo

生成package.json

cnpm init -y

编写 index.ts 文件

let message:string = "Hello World"
console.log(message)

let num:string = 10
let message2: string = `${num}`
console.log(message2);

运行ts文件

关于tsconfig.json⽂件

tsconfig.json ⽂件是 TypeScript 项⽬的配置⽂件。通过 tsconfig.json ⽂件,我们可以指定编译器的选项以⾃定义 TypeScript 编译的⾏为。
放在项⽬的根⽬录
tsconfig.json⽂件主要供tsc编译器使⽤

通过运⾏ 下⾯指令⽣成tsconfig.json⽂件

tsc –init

以下是常⻅配置:

  1. compilerOptions (编译器选项):这是 tsconfig.json ⽂件中最常⻅的选项之⼀。通过 compilerOptions ,我们可以指定编译器的⾏为。常⻅的编译器选项包括:
    • target (⽬标代码的 ECMAScript 版本):指定编译后的 JavaScript 代码要符合的 ECMAScript 版本。
    • module (模块系统):指定 TypeScript 代码使⽤的模块系统,如 CommonJS、AMD、ES2015 等。outDir (输出⽬录):指定编译后的 JavaScript ⽂件的输出⽬录。
    • sourceMap (源码映射):指定是否⽣成源码映射⽂件,以便在调试时能够⽅便地追踪 TypeScript 代码。
    • strict (严格模式):指定是否启⽤ TypeScript 的严格模式,以应⽤更严格的类型检查规则。
    • include 和 exclude (包含和排除⽂件):⽤于指定要包含和排除的⽂件,⽀持使⽤通配符模式。
    • baseUrl 和 paths (模块解析):⽤于配置 TypeScript 的模块解析规则,可以指定模块的基础路径和路径别名。
  2. include 和 exclude (包含和排除⽂件):这两个选项⽤于指定要包含和排除的⽂件。在 include 中可以使⽤通配符模式来匹配⽂件,⽽在 exclude 中可以指定要排除的⽂件或⽂件夹。
  3. references (引⽤其他项⽬):这个选项⽤于指定要引⽤的其他 TypeScript 项⽬。通过引⽤其他项⽬,我们可以在⼀个项⽬中使⽤另⼀个项⽬的类型定义⽂件。
  4. files (⽂件列表):这个选项⽤于⼿动指定要编译的⽂件列表。如果指定了 files ,则只会对这些⽂件进⾏编译,⽽不会考虑 include 和 exclude 。

方式一:原始调适方式

  1. 编译并监听ts文件

打开一个终端,执行下面的命令

tsc --init # 初使化文件
tsc -w  # 把ts编译成js文件,并监听 index.ts 文件, 并实时会生成 index.js 文件
  1. 再打开一个终端,执行 node index.js
% node index.js
Hello World
10

原理是编辑成 js 文件后,再执行

方式二: ts-node 编译并执行ts文件

  1. 安装插件
% cnpm i ts-node --g
% ts-node -v
v10.9.2
  1. 安装 @types/node

nodejs 环境执行ts

cnpm i @types/node -D
或者
cnpm i @types/node –save-dev (node环境支持的依赖必装)

  1. 编写 index.ts 文件
let message:string = "Hello World"
console.log(message)
  1. 编译并执行ts文件
% ts-node index.ts
Hello World

目录结构

% tree     
.
├── index.js
├── index.ts
├── node_modules
│   └── @types
│       └── node -> ../.store/@types+node@22.5.0/node_modules/@types/node
├── package.json
└── tsconfig.json

原始数据类型

Boolean、Number、String、null、undefined 以及 ES6 的 Symbol 和 ES10 的 BigInt。

1. 原始数据类型:

  • boolean
  • number
  • string
  • undefined
  • null
  • symbol

2. 对象类型:

  • 对象(object)
  • 数组(Array)
  • 元组(Tuple)
  • 枚举(enum)
  • 函数(function)

3. 其他类型:

  • any
  • never
  • unknown
  • void 值类型

typescript要求在变量声明的时候要声明值的类型,如下

let 变量名:类型=数据

注意,上⾯所有类型的名称都是⼩写字⺟,⾸字⺟⼤写的 Number 、 String 、 Boolean 等在 JavaScript 语⾔中都是内置对象,⽽不是类型名称。

原始数据类型的声明⽅式案例

//string
let a:string="hello" 
let b:string
var c:string="aa" 
const d:string="bb" 
//number
let n:number=123 
//boolean
let boo:boolean=true 
//undefined
let u:undefined=undefined 
//null
let nu:null=null 
//symbol
let s:symbol=Symbol()

其他类型

1. any类型

any表示的是任意类型,可以任意赋值,⼀个变量设置类型为any,相当于对该变量关闭了类型检测如果声明⼀个变量不设置类型,其实也是any类型。所以在开发中不建议使⽤该⽅法

2. unknown类型

unknown相对于any是安全的
要想正常使⽤unknown,必须保证操作是合法的

let a:unknown=5;

if(typeof(a)=="number"){ 
    console.log(a*2) 
}else if(typeof(a)=="string"){ 
    a.substring(1)
}

3. never类型

never表示永远不会有返回值的类型,⽐如抛出异常,或者死循环,那么该函数永远执⾏不完,不可能有返回值

4. 值类型

TypeScript 规定,单个值也是⼀种类型,称为“值类型”。

let a:123=123 
let b:"hello"="hello"

数组和元组

1. 数组

ts中规定,数组中所有成员的类型必须相同,数量可以不确定

数组的声明语法:

let arr:类型[ ]=[ ]
或者
let arr:Array<类型>=[ ]  //这种写法本质上属于泛型

使⽤案例

//声明直接赋值
let arr:string[]=["a","b"]
//先声明再赋值
let arr2:number[]
let arr3:boolean[]
arr2=[1,2,3]
//后续添加的元素也必须符合数组的类型
arr.push("8")
//⼆维数组
let arr4:string[][]=[["a","b"],["e","f"]]
//对象数组
let arr:{name:string,age:number}[]=[{name:"aa",age:18},{name:"bb",age:17}] //函数数组
let arr: (()=>number)[]=[function(){return 123},function(){return 443}] //定义包含多个数据类型的数组
let arr:(string|number|(()=>void))[]=["hh",123]

2. 元组

元组可以包含不同类型的元素,每个元素具有预定义的位置。需要为每⼀个元素规定类型

let arr:[类型1,类型2]=[数据1,数据2]

let arr:[string,number,boolean]=["A",123,true] //先声明再赋值
let arr2:[boolean,string]
arr2[0]=true; 
arr2[1]="123"; 
//如果后续通过任何⽅法向数组添加数据,也可以,后添加的数据是前⾯每个数据的联合类型
arr2.push("123")

对象

对于对象来说,我们应该限定对象中每个属性的类型,⽽不是限定对象这个整体的类型

基本语法

let obj:{name:string,age:number}={name:”⼩明”,age:18}

案例

let a:{age:number,name:string}={name:"张三",age:18} //先声明再赋值
let a2:{salary:number,address:string} 
a2={salary:3500,address:"北京"}
//添加属性
a2.salary=4500

1.可选属性

属性名后⾯加问号,代表该属性可有可⽆,⼀个对象中可以有任意多个可选属性

let a:{name:string,age?:number} 
a={name:"hello"} //正常执⾏,因为age可以不给

2.任意属性

如果我只希望⼀个对象必须具有a属性,其他的属性有没有随意

let a:{name:string,[propName:string]:any}
//propName代表属性名,肯定是字符串,propName只是形参,可以换成别的名字 任意属性只有⼀个没有多个,它代表了其他的所有属性
//任意属性的类型⼀定是其他类型(包含可选属性)的⽗类
a={name:"张三",age:18,salary:3500}

练习

let obj:{ 
    name:string, 
    like:string[], 
    pet:{name:string,age:number},     
    [propName:string]:any 
}

obj={
    name:"张三",
    like:["唱歌","睡觉","打游戏"], 
    pet:{name:"旺财",age:2},
    girlFriend:{ 
        name:"刘亦菲", 
        age:18,
    } 
}

let obj:{ 
    run:(height:number)=>void
}

obj={ 
    run:function(height:number){
        console.log("i can run")
    } 
}

3.只读属性

在对象属性的前⾯加上readonly,代表该属性只能访问,不能修改,⼀个对象可以有任意多个只读属性

let obj:{readonly name:string,age:number} 
obj={name:"⼩红",age:18} 
obj.age=20;//正确
obj.name="哈哈" //错误,因为是只读的

4.关于内置对象

let b: Boolean = new Boolean(1);
let e: Error = new Error('Error occurred');
let d: Date = new Date();
let r: RegExp = /[a-z]/;
let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');

函数

1.基本使⽤

函数的类型声明,需要在声明函数时,给出参数的类型和返回值的类型。

function fn(m:number,n:string):string{ 
    return n+m
}

如果没有返回值,就是void类型

function fn(m:number,n:string):void{ 
    console.log(m+n)
}

通过变量赋值的形式声明函数

let fn=function(m:number,n:string):void{
    console.log(m+n)
} 
//换成箭头函数的写法
let fn=(m:number,n:string):void=>{
    console.log(m+n)
}

单独定义函数类型

let 变量名:(参数1:类型,)=>返回值类型
let fn3:(a:number)=>number

// fn3=()=>{
//     console.log(123) 
// } 

fn3=function(a:number):number{ 
    return 123
}

事实上,上⾯的代码只对等号右侧的匿名函数进⾏了类型定义,⽽等号左边的 fn,是通过赋值操作进⾏类型推论⽽推断出来的。如果需要我们⼿动给 fn添加类型,则应该是这样:

let fn:(m:number,n:string)=>void=(m:number,n:string):void=>{console.log(m+n)}

⼯作中声明函数,更推荐使⽤通过function声明的⽅式

2.可选参数

如果某个参数是可选的,那么要在参数后⾯加问号
⼀个函数可以有多个可选参数
注意:
可选参数必须接在必需参数后⾯。换句话说,可选参数后⾯不允许再出现必需参数了:

function fn(m:number,n?:string):void{ 
    console.log(m+n)
}
fn(8)

3.参数省略

函数的实际参数个数,可以少于类型指定的参数个数,但是不能多于,即 TypeScript 允许省略参数。

let fn:(a:number, b:number) => number;
fn = (a:number) => a;//正确
fn = (a:number, b:number,c:number) => a;//错误

这是因为 JavaScript 函数在声明时往往有多余的参数,实际使⽤时可以只传⼊⼀部分参数。
⽐如,数组的forEach()⽅法的参数是⼀个函数,该函数默认有三个参数(item, index, array) => void,实际上
往往只使⽤第⼀个参数(item) => void。
因此,TypeScript 允许函数传⼊的参数不⾜。

4.rest参数

rest 参数表示函数剩余的所有参数,它可以是数组(剩余参数类型相同),也可能是元组(剩余参数类型不同)。

// rest 参数为数组
function joinNumbers(...nums:number[]) { 
    // ...
}
// rest 参数为元组
function f(...args:[boolean, number]) {
    // ...
}

5. 默认参数

<script setup lang="tsx" name="organizationOrgIndex">
import { useRouter } from "vue-router";

// 获取当前路由对象
const router = useRouter();

// 跳转到用户列表,并带上组织 ID
const navigateToUserList = (organizationId: number, openAddUserDialog: string = "false") => {
// 路由跳转
  router.push({
    path: "/organization/user",
    query: { organizationId: Number(organizationId), openAddUserDialog: openAddUserDialog }
  });
};
</script>

// 调用方法
<el-button type="primary" link :icon="Plus" @click="navigateToUserList(scope.row.id, 'true')">新增员工</el-button>

联合类型

联合类型(Union Types)表示取值可以为多种类型中的⼀种。

//联合类型使⽤ | 分隔每个类型。
var val:string|number |string[]|()=>number
val = 12 //ok
val = "hello" //ok

所以我们之前定义存储不同数据数组的时候,也可以使⽤联合类型

const arr: (number | string)[] = [1, "string", 2];

特殊的,如果访问联合类型的属性或⽅法:
当 TypeScript 不确定⼀个联合类型的变量到底是哪个类型的时候
我们只能访问此联合类型的所有类型⾥共有的属性或⽅法:


function getLength(something: string | number): number {
    return something.length;
}
// index.ts(2,22): error TS2339: Property 'length' does not exist on type 'string | number'.
// Property 'length' does not exist on type 'number'

访问 string 和 number 的共有属性是没问题的

function getString(something: string | number): string { 
    return something.toString();
}

联合类型的写法

let a:string|number|string[]|{name:string,age:number}|(()=>string);
a="hello";
a=123;
a=["a","b","c"]
a={name:"张三",age:18}
a=function(){
    return "hello"
}

类型别名

在TypeScript中,类型别名是给现有类型取⼀个新的名字。它可以⽤于提⾼代码的可读性和可维护性,以及减少重复的类型定义。

1. 最基本的使⽤⽅式

type MyString = string;
let a:MyString="hello"

//type关键字可以为原始值、联合类型、元组以及任何我们定义的类型起⼀个别名

type Add = (x: number, y: number) => number;
let add: Add = (arg1: string, arg2: string): string => arg1 + arg2; // error 不能
将类型“(arg1: string, arg2: string) => string”分配给类型“Add”
type Directions = 'up' | 'Down' | 'Left' |'Right' 
let toWhere : Directions ='Down'

2. 对象数组使⽤类型别名

const objArr: { name: string, age: Number }[] = [ 
    { name: "⼩明", age: 18 },
    { name: "⼩红", age: 28 },
];
//上⾯的案例使⽤类型别名简写
type Person = { name: string, age: Number }; const arr:Person[]= [
    { name: "⼩明", age: 18 },
    { name: "⼩红", age: 28 },
];

3. 联合类型写法

结合之前联合类型的写法

type A={name:string}
type B=number
type C=A|B|"哈哈"|string
let str:C=8

类型推论

如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出⼀个类型。

  1. 以下代码虽然没有指定类型,但是会在编译的时候报错:
    let a=1;
    a="hello" //error: Type 'string' is not assignable to type 'number'.
  2. 如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型⽽完全不被类型检查:
let a; 
a="hello"; //正确
a=7; //正确
  1. 函数的参数的类型推论
function fn(x,y){ 
    //x y被推断为any 
    console.log(x+y) 
}

typeof和keyof运算符

1. typeof

JavaScript ⾥⾯, typeof 运算符只可能返回⼋种结果,⽽且都是字符串。

typeof undefined; // "undefined"
typeof true; // "boolean"
typeof 1337; // "number"
typeof "foo"; // "string"
typeof {}; // "object"
typeof parseInt; // "function"
typeof Symbol(); // "symbol"
typeof 127n // "bigint"

TypeScript 将 typeof 运算符移植到了类型运算,它的操作数依然是⼀个值,但是返回的不是字符串,⽽是该值的 TypeScript 类型。

const a = { x: 0 };
type T0 = typeof a;   // { x: number }
type T1 = typeof a.x; // number

ts中的typeof是 根据已有的值 来获取值的类型 来简化代码的书写

const myVariable = 42;
type MyVariableType = typeof myVariable;  // MyVariableType 的值为 "number"

2. keyof

keyof运算符接受⼀个对象类型作为参数,返回该对象的所有键名组成的联合类型。
keyof 类型别名
keyof {}

练习

type Person={name:string,age:number}
type MyType=keyof Person //name|age
//type MyType=keyof {name:string,age:number} //name|age
let a:MyType="name"

映射类型

接⼝

enum枚举类型

泛型

class类

模块

namespace

declare关键字

tsconfig.json⽂件详细配置

作者:海马  创建时间:2024-08-27 07:54
最后编辑:海马  更新时间:2025-01-03 13:55