Typescript之从零开始学习笔记
文章目录
- Typescript之从零开始学习笔记
- 1.环境搭建
-
- [1. 安装node.js](#1. 安装node.js)
- [2. 安装typescript](#2. 安装typescript)
- [3. 使用tsc对ts进行编译](#3. 使用tsc对ts进行编译)
- [2. TS 配置](#2. TS 配置)
-
- [1 编译器配置](#1 编译器配置)
-
- [1. 生成配置文件](#1. 生成配置文件)
- [2. 自动编译](#2. 自动编译)
- [3. 发生错误](#3. 发生错误)
- [3. 基本语法](#3. 基本语法)
-
- [1. 静态类型检查](#1. 静态类型检查)
- 2.基本数据类型
- [3. 数组类型](#3. 数组类型)
- [4. any类型](#4. any类型)
- [5. 函数的参数类型](#5. 函数的参数类型)
- 6.函数形参为对象类型
- [7. 联合类型](#7. 联合类型)
- [8 类型别名](#8 类型别名)
- [9. 类类型](#9. 类类型)
- 10.接口类型
- [11. 类型断言](#11. 类型断言)
- [12. 模板文字类型(Template Literal Types)](#12. 模板文字类型(Template Literal Types))
- [13. TS特殊符号用法](#13. TS特殊符号用法)
- [4. type与接口扩展字段类型区别](#4. type与接口扩展字段类型区别)
官网:https://www.typescriptlang.org/
官网文档:https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html
1.环境搭建
1. 安装node.js
官网下载直接安装即可(安装过程略)
2. 安装typescript
- 安装
sh
# npm i -g typescript
C:\Users\infodba>npm i -g typescript
D:\Program Files\nodejs\node_global\tsc -> D:\Program Files\nodejs\node_global\node_modules\typescript\bin\tsc
D:\Program Files\nodejs\node_global\tsserver -> D:\Program Files\nodejs\node_global\node_modules\typescript\bin\tsserver
+ typescript@4.5.4
added 1 package from 1 contributor in 5.696s
- 查看typescript版本
shell
# tsc -v
C:\Users\infodba>tsc -v
Version 4.5.4
3. 使用tsc对ts进行编译
typescript
tsc xxx.ts
2. TS 配置
1 编译器配置
1. 生成配置文件
shell
# 1. 生成配置文件
tsc --init
PS F:\2022WebStudy\yuan-ts-study\yuan-ts-study> tsc --init
Created a new tsconfig.json with: TS
target: es2016
module: commonjs
strict: true
esModuleInterop: true
skipLibCheck: true
forceConsistentCasingInFileNames: true
You can learn more at https://aka.ms/tsconfig.json
#tsc --init 命令执行完后默认会在当前目录下生成tsconfig.json文件
tsconfig.json
配置文件内容如下:
json
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
// "incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment 默认加载的是es2016也即es7,可以配置es3|es5|es6|es7等来兼容低版本浏览器的js支持 */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
//指定ts源文件目录
"rootDir":"./src",
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
//指定编译后的ts输出目录
"outFile": "./dist",
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking 强制语法检查, */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
2. 自动编译
在vscode工具中使用下面命令会开启自动编译监听,当xxx.ts编写完成后会自动触发编译器并编译成xxx.js文件
shell
# 2. 自动编译
tsc --watch
3. 发生错误
如果ts中写了编译成js文件运行时异常的代码,ts在编译成js时默认会编译通过,而执行js时才会报错,如果想要再编译时直接抛出异常,则使用下面命令
shell
# 3. 发出错误
tsc -onEmitOnError hello.ts
3. 基本语法
1. 静态类型检查
2static-typecheck.ts
内容如下:
ts
/**静态类型检查 */
const msg = "hello"
msg()
/**
编译会出现如下错误:
2.static-typecheck.ts:4:1 - error TS2349: This expression is not callable.
Type 'String' has no call signatures.
4 msg()
*/
2.基本数据类型
3datatype-base.ts
内容如下
ts
/** 数据类型---基本数据类型*/
let age: number = 20;
let userName: string = 'jinshengyuan'
let gender: boolean = true
let person: any = {
"name":"jinshengyuan",
"code":"001"
}
let date: Date = new Date()
console.log(`${age} type is ${typeof age}`)
console.log(`${userName} type is ${typeof userName}`)
console.log(`${gender} type is ${typeof gender}`)
console.log(`${person} type is ${typeof person}`)
console.log(person.name,"=============="+person.code)
console.log(`${date} type is ${typeof date}`)
# 执行结果如下:
PS F:\2022WebStudy\yuan-ts-study\yuan-ts-study\dist> node .\3datatype-base.js
20 type is number
jinshengyuan type is string
true type is boolean
[object Object] type is object
jinshengyuan ==============001
Sat Jan 15 2022 16:18:50 GMT+0800 (中国标准时间) type is object
3. 数组类型
数组定义有两种方式:
- 普通方式:let v:dataType [] = []
- 泛型方式:let v:Array = []
ts
/**
* 数据类型-数组
* 有两种方式:
* 1.普通方式
* let v:dataType [] = []
* 2.泛型方式
* let v:Array<dataType> = []
* */
//1. variable:dataType []
let numArr: number[] = [1, 3, 34, 904]
numArr.forEach(num => {
console.log(num);
});
console.log("=======================")
// 2.泛型方式
let strArr: Array<string> = ['a', 'b', 'c']
strArr.forEach(str => {
console.log(str)
})
/*** 执行结果如下:
1
3
34
34
=======================
a
b
c
*/
4. any类型
不希望某个特定值导致类型检查错误时可以使用any类型
ts
/** 数据类型-any */
let obj: any = {
userName: 'jinshengyuan',
gender: true,
age: 27,
birthday: 'xxxx-xx-xx'
}
console.log(obj.userName)
//jinshengyuan
/** 数据类型-any */
let obj: any = {
userName: 'jinshengyuan',
gender: true,
age: 27,
birthday: 'xxxx-xx-xx'
}
console.log(obj.userName)
//jinshengyuan
//objOne后面不跟数据类型,ts会根据属性的值自动推断具体的类型
let objOne = {
userName: 'jinshengyuan',
gender: true,
age: 27,
birthday: 'xxxx-xx-xx'
}
5. 函数的参数类型
6datatype-funcation.ts
如下
ts
/** 数据类型-函数形参类型定义 */
// 1.函数形参指定类型
let f1 = (name: string, age: number) => {
console.log(`${name}已经${age}岁了`);
}
f1('jinshengyuan', 22)
//2.函数无返回值类型指定
function f2(a: number, b: number): void {
console.log(`${a}+${b}=${a + b}`)
}
f2(2, 33)
//3.函数有返回值类型指定
function f3(a: number, b: number): number {
return a + b;
}
let f3_result = f3(3, 4)
console.log("f3_result:" + f3_result)
//4.类型推断
const names = ['zhangsan', 'lisi', '王五']
names.forEach(function (name) {
//这里虽然name没有显示的指定类型,但ts将names中每一个元素自动推断为string类型,就可以直接调用string类型的方法
console.log(name.toUpperCase())
})
//或使用箭头函数
names.forEach(name => {
console.log(name.toUpperCase())
})
6.函数形参为对象类型
函数形参中是一个对象,则对象的每个属性的类型后用
,
或;
分割;若对象参数中某个属性的值可选,则属性后需要跟
?
表示此属性值可指定也可不指定,否则必须指定值若对象参数中某个属性的值可选且为string类型,则此时调用spring类型的方式时必须也跟上
?
,否则ts编译报错
ts
/**数据类型-对象类型指定 */
//1.函数形参中是一个对象,则对象的每个属性的类型后用,或;分割
// , 分割
function myAxisA(pt: { x: number, y: number }) {
console.log("坐标A:" + pt.x, pt.y)
}
// ; 分割
function myAxisB(pt: { x: number; y: number }) {
console.log("坐标B:" + pt.x, pt.y)
}
const pointDataA = {
x: 22,
y: 33
}
myAxisA(pointDataA);
const pointDataB = {
x: 100,
y: 300
}
myAxisB(pointDataB);
/***
坐标A:22 33
坐标B:100 300
*/
//2.若对象参数中某个属性的值可选,则属性后需要跟`?`表示此属性值可指定也可不指定,否则必须指定值
function printName(person: { name: string, age?: number }) {
console.log(person.name)
}
//不传age属性也能编译通过及正常打印
printName({
name: 'jinshengyuan'
})
//传age属性能编译通过及正常打印
printName({
name: 'jinshengyuan',
age: 33
})
//3. 若对象参数中某个属性的值可选且为string类型,则此时调用spring类型的方式时必须也跟上`?`,否则ts编译报错
function printName1(obj: { name: string, code?: string }) {
//新式优雅写法,在对象的属性名后加入`?`
console.log(obj.code?.toUpperCase())
//原始写法
if (obj.code != undefined) {
console.log(obj.code.toUpperCase())
}
}
printName1({
name: '张三',
code: 'zangSan'
})
7. 联合类型
联合类型中间使用管道符
|
进行分割
ts
/** 数据类型-联合类型 let v:numver|string|boolean */
// 联合类型中间使用管道符`|`进行分割
//1.printInfo函数的id属性类型可以为数值、字符串、数组三种类型
function printInfo(id: number | string | Array<string>) {
console.log("只为:" + id + "类型为:" + typeof id)
}
printInfo(222)
printInfo('aaa')
printInfo(['a', 'b', 'c'])
/*
222类型为:number
aaa类型为:string
a,b,c类型为:object
*/
//2.如果v传入的是数组,则在后面追加z,否则输出hello
function hello(v: string[] | string) {
if (Array.isArray(v)) {
console.log(v.join("z"))
} else {
console.log("hello")
}
}
hello(['x', 'y'])
hello("hi")
/*
xzy
hello
*/
//3. 多种类型共有的方法,如数字素组与字符窜都有截取元素的方法`slice()`
function publicM(x: number[] | string) {
//截取前三个元素
console.log(x.slice(0, 3))
}
publicM([1, 3, 34, 46, 4, 67, 90, 7, 5])
publicM('helloword')
/*
[ 1, 3, 34 ]
hel
*/
8 类型别名
ts中定义参数类型时都是变量名在前而数据类型在后,类型别名就是将类型放在变量名称前边,类似与Java中声明变量的方式
类型别名使用
type
关键字指定,且给变量赋值的是具体的数据类型,如type id = string|number
,可以是时任何类型;type 关键字后边如果如果是一个对象类型,则对象的属性指定类型有三种写法,区别在于属性之间用
,
|;
|\n
进行分割作用目的:可以时同一类型多次重复使用
ts
/** 数据类型-类型别名 语法: type x = string|number */
// 类型别名为pointType的类型为string 或 number
type pointType = string | number
// 类型为 point 的类型是对象,对象中的属性类型=别名为pointType的类型
//[注意:下面指定类型别名的方式等价,即:point=pointA=pointB,区别在于 `,`|`;`|`\n`]
//1.属性指定用`,`隔开
type point = {
x: pointType,
y: pointType
}
// 2. 属性之间用`;`隔开
type pointA = {
x: pointType;
y: pointType
}
// 3. 属性之间换行,写在一行是不行的
type pointB = {
x: pointType
y: pointType
}
function getPoint(pt: point) {
console.log("坐标:" + pt.x + "," + pt.y)
}
getPoint({
x: '220',
y: 333
})
getPoint({
x: 100,
y: 200
})
/*
坐标:220,333
坐标:100,200
*/
9. 类类型
ts
class Demo {
a: number;
b: number;
constructor(a: number, b: number) {
this.a = a;
this.b = b;
}
getDemo() {
return `(${this.a}, ${this.b})`;
}
}
const demo = new Point(5, 7);
demo.getDemo() // (5, 7)
10.接口类型
- 接口以
interface
关键字开头,且变量名大写;- 接口可以继承接口
ts
/** 数据类型-接口 */
//1. 定义一个动物接口
interface Animals {
name: string;
age: number;
}
//dog函数形参指定为接口类型
function dog(dog: Animals) {
console.log(dog.name, dog.age);
}
dog({ name: '小狗', age: 4 })
//2. 接口继承接口类型,Ant继承Animals
interface Ant extends Animals {
like: string;
day: number;
}
function ant(ant: Ant) {
console.log(`小蚂蚁${ant.name} ${ant.age}岁了,${ant.like}每${ant.day}天搬家一次`)
}
// 继承自父接口的属性必须指定全,否则编译不通过
ant({ name: '土豆', age: 4, like: "喜欢", day: 5 })
// 3. 向现有类型中添加字段,可以多次声明后直接将属性合并到一起
interface MyInfo {
name: string;
}
interface MyInfo {
age: number;
}
interface MyInfo {
gender: boolean;
}
const myinfo: MyInfo = {
name: "张三",
age: 33,
gender: true
}
//===========type 扩展字段类型==============
// 1. 声明对象类型
type Animal = {
name: string;
}
//2.扩展字段类型
type Tigger = Animal & {
hobby: string
}
const tigger: Tigger = {
name: "老虎",
hobby: "吃肉"
}
//3. type声明的类型对象是不可更改的,所以不能添加类型字段
11. 类型断言
语法:就是在获得的某个DOM元素后,在元素前面加泛型或在元素之后通过
as
关键字指定元素的具体类型有两种写法:
- const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement
- const myCanvas = document.getElementById("main_canvas")
ts
/** 数据类型-类型断言 */
const myCanvas1 = document.getElementById("main_canvas") as HTMLCanvasElement
const myCanvas2 = <HTMLCanvasElement>document.getElementById("main_canvas")
//
const x = ('hello' as any) as string
// unknow 未知类型
const y = ('22' as unknown) as number
12. 模板文字类型(Template Literal Types)
13. TS特殊符号用法
- 属性或参数中使用 ?:表示该属性或参数为可选项
- 属性或参数中使用 !:表示强制解析(告诉typescript编译器,这里一定有值),常用于vue-decorator中的@Prop
- 变量后使用 !:表示类型推断排除null、undefined
4. type与接口扩展字段类型区别
相同点:
- 都可以定义对象属性的类型
- 都可以扩展字段类型,type 通过
&
符合扩展字段类型,interface通过extends
关键字来扩展字段类型不同点:
接口支持向已有类型对象中添加属性,而type不支持
- 扩展字段方式不同
ts
//1. 接口-通过`extends`关键字继承父接口来扩展字段
interface Animals {
name: string;
age: number;
}
//接口继承接口类型,Ant继承Animals
interface Ant extends Animals {
like: string;
day: number;
}
//dog函数形参指定为接口类型
function dog(dog: Animals) {
console.log(dog.name, dog.age);
}
dog({ name: '小狗', age: 4 })
//2. type-通过 `&` 符合来扩展字段
type Animal = {
name: string;
}
// type 扩展字段类型
type Tigger = Animal & {
hobby: string
}
const tigger: Tigger = {
name: "老虎",
hobby: "吃肉"
}
- 向现有的对象类型中添加字段
- 接口通过多次声明同名的接口方式来添加字段,使用时会将属性合并到一起;
- type一旦声明了字段类型是不可更改的,所以不支持添加字段
ts
// 1.interface-向现有类型中添加字段,可以多次声明同名的接口后直接将属性合并到一起
interface MyInfo {
name: string;
}
interface MyInfo {
age: number;
}
interface MyInfo {
gender: boolean;
}
const myinfo: MyInfo = {
name: "张三",
age: 33,
gender: true
}
// 2.type-不支持向现有类型对象中添加字段