TypeScript快速上手
一、TypeScript前置工作
我这里用的是yarn,用npm也可以
yarn init --yes 创建项目
yarn add typescript --dev 安装 TypeScript 模块
yarn tsc --init 生成 ts 配置文件
先简单了解下ts配置文件
// 这里是删减版本
{
"compilerOptions": {
"target": "ES5", /* ts编译成ECMAScript对应版本的js,最低是ES3,ES6开始最好写成ES2015~ES2020*/
"lib": ["ES2015","DOM"],/* 引用的标准库 */
"outDir": "dist",/* 编译好的js文件输出到dist目录 */
"rootDir": "src", /* 要编译的文件夹,会把文件夹内的ts文件都进行编译 */
"strict": true, /* 变量的值默认是否可以为空(null),true是不允许为空 */
}
}
TypeScript文件后缀名都是ts,例如 src/getting-started.ts
后续编译也只会将ts文件编译为js文件
二、TypeScript原始类型
// 在typeScript中,值默认是可以为空(null)的,配置中如果设置了"strict": true则不允许为空
const a: string = "憨憨"
const b: number = 123
const c: boolean = true
const d: null = null
const e: undefined = undefined
// ES2015之后Symbol也是原始类型,在没修改过ts配置的时候这里会报错,具体原因我们下面会讲到
const f: symbol = Symbol()
三、将ts文件编译成js文件
// 加上 --local zh-CN编译会有中文的错误提示,如果不需要去掉即可
yarn tsc --locale zh-CN
四、Symbol原始类型报错的原因
我们ts配置中的 “target”:“es5”,所以会引用es5的标准库,而es5中没有定义Symbol类型,所以会有报错。
解决方法有两种
1、修改 “target”:“es2015”
2、启用配置中的 lib选项,指定引用es2015的标准库
而在设置了 “lib”:[“ES2015”]后
console.log("打印数据")// console.log()就会报错
原因是lib中只设置了ES2015,把其他的默认标准库覆盖了,所以我们需要把其他标准库添加回来
需要注意的是,typeScript中把BOM和DOM归结到一个标准库DOM当中了,所以只需要添加一个DOM。
即:
"lib": ["ES2015","DOM"]
标准库就是内置对象所对应的声明,我们在代码中使用内置对象就要使用对应的标准库,否则typeScript就找不到对应的类型,就会报错
五、声明同名变量检测异常问题
在同一目录下的不同ts文件中,如果声明的变量重名了,语法检测会提示出来。这是作用域的问题,因为这些变量都是声明在全局上的,所以会被检测到,然后提示错误。
解决方法一:将变量声明在函数内部
(function(){
const hello:string = "hello"
})()
解决方法二:将文件模块化(推荐)
export {} // 在ts文件中添加即可
六、ts定义对象类型
const foo: object = function(){}
const obj:{foo: string, bar: number} = {foo: "憨憨", bar:123}
七、ts定义数组类型
const arr1: Array<number> = [1, 2, 3]
const arr2: number[] = [1, 21, 2]
function sum(...args: number[]){
return args.reduce((prevent, current) => prevent + current, 0)
}
sum(1, 2)
八、元组
// 元组就是明确元素数量以及每个元素类型的数组
const tuple: [number, string] = [18, 'hello']
// const age = tuple[0]
// const name = tuple[1]
const [age, name] = tuple
九、枚举类型
通过enum关键字定义
export {}
const enum Status{
Default = 0,
Success = 1,
Fail = 2
}
// 没有设置初始值的情况下,默认为第一个元素赋值为 0,后面的元素会在第一个元素的值上递增
enum Status2{
Default,// 0
Success,// 1
Fail// 2
}
// 没有设置初始值的情况下,默认从 0 开始
enum Status3{
Default = 6,// 6
Success,// 7
Fail// 8
}
// 如果第一个元素赋值为字符串,后面的元素也必须手动赋值
enum Status4{
Default = "aaa",
Success,
Fail
}
const post = {
title:"this is title",
statue: Status.Default
}
十、ts声明函数
export {}
// 参数一为number类型,参数二为string类型,剩余参数必须为数字类型,返回值为string类型
function fn(a: number, b:string, ...rest:number[]): string{
console.log(rest);
return "function"
}
fn(1, '2', 3, 4)
// 写法与上面有些区别,实际上是一样的
const f1:(a: number, b: number) => string = function(a: number, b: number): string{
return '憨憨'
}
f1(1, 2)
十一、任意类型Any
export {}
// 定义value是任意类型,语法检测上不会有任何问题,但实际运行可能会有问题,建议少用
function stringify(value: any){
return JSON.stringify(value)
}
stringify('哈哈哈')
stringify(100)
stringify(true)
let foo: any = "string"
foo = 123
foo.bar()
十二、隐式类型推断
在typescript中,如果我们没有通过注解去明确标注一个变量的类型,那么typeScript会根据这个变量的使用情况去推断这个变量的类型
这种特性叫做:隐式类型推断
let age = 19 // 隐式推断age为number类型
age = "憨憨" // 这里会报错
let foo;// 隐式推断foo为any类型,所以一下代码都不会报错
foo = "hanhan"
foo = 100
// 建议还是要为每个变量添加明确的类型注解,这样有助于理解代码
十三、类型断言
const nums: number[] = [110, 120, 119, 911]
// 这里 res 一定是一个数字,但是 typeScript 不知道,它推断这里是一个number或者undefined
const res = nums.find(i => i > 0)
// 所以我们不能直接将 res 当做数字取用
// const square = res * res
// 这种情况下我们可以断言这个变量是一个number类型的
// 断言方式一:as
const num1 = res as number
// console.log(num1 * num1);
// 断言方式二
const num2 = <number>res
// 在JSX下不能使用,因为会和JSX中的标签产生语法冲突
十四、接口 interface
接口就是用来约束一个对象的结构,一个对象去实现一个接口,就必须拥有接口当中所约束的所有成员
// 通过interface关键字定义接口
interface Post{
title: string
content: string
}
function printPost(post: Post){
console.log(post.title);
console.log(post.content);
}
printPost({
title:"this is a title",
content: 'this is a content'
})
十五、对接口的一些补充
export {}
interface Post{
title: string
content: string
subtitle?: string // 可选成员
readonly summary: string // 只读成员
}
const hello: Post = {
title: 'hello',
content: "hello text",
summary: "this is summary"
}
// 可以添加动态成员,键值都必须是string,这种接口看起来就和我们平常定义对象添加属性类似
interface Cache{
[key: string]: string
// [prop: number]: number
}
const cache: Cache = {
hhh: 'hhh'
}
cache.bar = 'bar'
cache.foo = "1"