TSTypeScript语法学习
Posted woodwhale
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TSTypeScript语法学习相关的知识,希望对你有一定的参考价值。
1、安装typescript
这一篇幅仅仅涉及到ts的基本语法,没有涉及到ts项目以及配置
typescript全局安装,我这里使用的是cnpm,npm或者yarn同理
cnpm install -g typescript
cnpm install -g ts-node
cnpm install -g tslib @types/node # 包含console等辅助函数的ts库
安装完毕之后输入tsc -v
查看版本,同时检查是否安装成功
2、变量
和kotlin一样,使用: (type)
来声明变量的类型
2.1 ES6原生类型
如下是ES6中的原生类型
let num: number = 0xdeadbeef
let bol: boolean = true
let str: string = "woodwhale"
let nul: null = null
let und: undefined = undefined
let obj: object = new String("sheepbotany")
2.2 任意类型
任意类型包括两种,一种是any
,一种是unknow
其中,any类型可以调用属性和方法,unknow无法调用
let anys: any = "我是任意的,随便赋值"
anys = 114514 // number
anys = false // 布尔
anys = null
anys = undefined
anys = [] // 数组
anys = a: 123, b: ():number => 114514 // 字典
anys.a // 可以调用属性和方法
anys.b()
let unk: unknown = "未知类型,比any安全"
unk = a: 123
// unk.a 无法调用
再来看第二个区别,any
可以当作父类也可以当作子类,unkown
只能当作父类、不能当作子类。
如果非要给unknow赋值,可以给其赋值any类型的变量或者unknow类型的变量
let test: any = "test"
let test2: string = "test2"
test2 = test // 可以
console.log(test2)
let test3: unknown = "test3"
// test2 = test3 不可以
test3 = test // 可以
2.3 数组类型
两种形式,面向结构和面向对象
let str_arr: string[] = ["1","1","4","5","1","4"]
let num_arr: number[] = [1,1,4,5,1,4]
let any_arr: any[] = [1,"1","4",[5],"1",4]
let bol_arr: boolean[] = [true,false]
let obj_arr: Array<string> = str_arr // Array接口
console.log(obj_arr)
如果是多维数组,使用下面的形式
let str2_arr: string[][] = [["1"],["2"]]
let obj2_arr: Array<Array<string>> = str2_arr
console.log(obj2_arr)
在ES6中多了一个...
的扩展运算符,用于取出参数对象中的所有可便利的属性,可以配合数组使用,这里拿函数举一个例子
function fun_arr(...args: any): void
console.log(args) // 传入参数的数组
console.log(arguments) // 内置的arguments对象
fun_arr(1,1,4,5,1,4)
/*
[ 1, 1, 4, 5, 1, 4 ]
[Arguments] '0': 1, '1': 1, '2': 4, '3': 5, '4': 1, '5': 4
*/
除此之外,我们可以使用接口来定义自己的数组
interface myNumberArr
[arr_index: number]: number
let my_arr: myNumberArr = [1,2,3,4]
console.log(my_arr)
/*
[1,2,3,4]
*/
2.4 联合类型
在ts中,声明变量的类型可以使用标识符 |
来进行类型的联合,例如我需要一个变量可以置为字符串,同时也可以置为数字,那么可以这样使用
// 联合类型,可以是字符串,也可以是数字
let phone_number: number | string = "1919810"
phone_number = 114514
// 联合类型使用的小例子
let fn = (flag: number | boolean): boolean =>
return !!flag
console.log(fn(1) === fn(true))
2.5 交叉类型
和联合类型相反,交叉类型必须满足多种类型的需求,必须同时满足
interface People // 人 的接口
name: string,
age: number
interface Man // 男人 的接口
sex: string
const woodwhale = (man: People & Man): void =>
console.log(man)
woodwhale(
name: "woodwhale",
age: 19,
sex: "我太男了"
)
/*
name: 'woodwhale', age: 19, sex: '我太男了'
*/
2.6 类型断言
这里所谓的断言可以理解为强制转换
,使用关键字as
来进行强转,或者使用<type>
来进行强转
let assertion_fun = (num: number | string):void =>
console.log((num as string).length) // 将num强转为string类型
console.log(<number>num) // num强转为number类型
assertion_fun("114514")
/*
6
114514
*/
2.7 自动推断
如果我们在ts中没有声明变量的类型,ts会进行自动推断
let _str = "woodwhale" // 自动推断为string类型
let _num = 114514 // 自动推断为数字类型
let _any // 自动推断为any类型
2.8 类型别名
在ts中使用type
关键字可以进行类型起别名的操作,这里演示联合类型与类型别名的使用
type sn = string | number
let str_or_num: sn = "114514"
str_or_num = 1919810
type还可以定义函数类型
type fun = () => string // 一个 无参数的 返回string类型的 方法
let my_fun: fun = function f()
return "114514"
// 或者匿名函数
let my_fun_without_name: fun = () => "1919810"
console.log(my_fun())
/*
114514
*/
type还可以指定变量的种类,起到限定的作用
type flag = true | false | "true" | "false" | 1 | 0
let flag:flag = true
2.9 元组类型
typescript中有一种类型叫做元组类型,是数组的变种,可以存放不同数据类型的数据
let arr:[string,number] = ["woodwhale",19]
console.log(arr)
/*
[ 'woodwhale', 19 ]
*/
arr.push("sheepbotany",21)
console.log(arr)
/*
[ 'woodwhale', 19, 'sheepbotany', 21 ]
*/
如果需要添加数据到元组中,使用push方法就可以,但是必须是申明过的数据类型之一(这里必须是string或number)
2.10 never类型
在ts中,never类型表示不可能达到的一种类型,例如既要满足是string,又要满足是number的交叉类型
type flag = true | false | "true" | "false" | 1 | 0
let flag:flag = true
或者我们定义一个异常的方法,也可以让方法返回值为never类型
function _error(error_msg:string):never
throw new Error(error_msg)
_error("test error")
但是在实际开发过程中,never类型
最重要的是一个检查机制
,例如在switch多分支选择
的时候,如果甲方需要添加新的需求,那么新程序员在补充shit山代码的时候,可能会没有考虑到switch中的分支导致项目错误,这个使用使用never类型的常量进行default的兜底处理
就非常重要了,这样就可以在ts编译的时候就发现错误
interface AAA
type: "AAA"
interface BBB
type: "BBB"
interface CCC
type: "CCC"
type ABC = AAA | BBB |CCC
let switch_type = (val:ABC) =>
switch (val.type)
case "AAA":
break
case "BBB":
break
default:
const check:never = val
break
在上述代码中,没有考虑到CCC
的情况,那么在default中会有一个check的检查报错,可以提醒我们代码有问题!
正常修改后的代码应该是如下:
let switch_type = (val:ABC) =>
switch (val.type)
case "AAA":
break
case "BBB":
break
case "CCC":
break
default:
const check:never = val
break
2.11 symbol类型
symbol类型是ES6的新特性之一,目的是为了拥有唯一性。
下面列出了几种方法,来测试symbol如何读取
let s: symbol = Symbol("woodwhale")
let s2: symbol = Symbol("woodwhale")
let map =
[s]: "value",
[s2]: "value2",
name: "woodwhale",
sex: 1
// foreach 循环,无法读取symbol的键
for (let key in map)
console.log(key)
/*
name
sex
*/
// 使用Objeck.keys方法获取键,也无法读取symbol的值
console.log(Object.keys(map))
/*
[ 'name', 'sex' ]
*/
// 使用Object.getOwnPropertyNames方法获取属性名也无法读取symbol
console.log(Object.getOwnPropertyNames(map))
/*
[ 'name', 'sex' ]
*/
// 使用JSON.stringify,也无法获取symbol
console.log(JSON.stringify(map))
/*
"name":"woodwhale","sex":1
*/
// 使用Object.getOwnPropertySymbols方法只能获取其中的symbol
console.log(Object.getOwnPropertySymbols(map))
/*
[ Symbol(woodwhale), Symbol(woodwhale) ]
*/
// 使用Reflect.ownKeys可以获取所有的键,包括symbol
console.log(Reflect.ownKeys(map))
/*
[ 'name', 'sex', Symbol(woodwhale), Symbol(woodwhale) ]
*/
在Symbol对象中有一个iterator
的属性,也叫做迭代器
,每一个可以遍历的数组都具有这个性质(自己写的类生成的对象是没有的),迭代器具有next()
方法,可以迭代到下一个位置
let _arr:Array<number> = [1,1,4]
let __arr:number[] = [1,33,4,5]
let it = _arr[Symbol.iterator]()
console.log(it.next())
console.log(it.next())
console.log(it.next())
console.log(it.next())
/*
value: 1, done: false
value: 1, done: false
value: 4, done: false
value: undefined, done: true
*/
其中value
就是当前迭代的值,done
表示是否迭代到头了
根据迭代器的性质,写一个迭代方法
function gen(arr: any)
let it = arr[Symbol.iterator]()
let flag = false
while (!flag)
let next = it.next()
flag = next.done
if (!flag) console.log(next)
gen(new Set([1, 4, 5, 6]))
/*
value: 1, done: false
value: 4, done: false
value: 5, done: false
value: 6, done: false
*/
ts的编写者肯定考虑到了上述场景的使用情况,所以直接用了一个of
关键字的语法糖来实现迭代生成
for (let item of new Set([1, 4, 5, 6]))
console.log(item)
/*
1
4
5
6
*/
到这里我们会发现 of
与 in
有什么区别呢,其实 of
是对容器中的值进行迭代,是一个获取值的方式,而 in
是对容器中的键进行遍历,是一个获取索引的方式
3、函数
ts的函数和js差不多,但是多了很多的拓展,这里列出一些比较常用的属性
-
默认参数函数
function fun_test(name: string, age: number): void console.log(name + age) // 携带默认参数的方法 function fun_test_with_default_args(name: string = "woodwhale", age: number = 19): void console.log(name + age) fun_test("woodwhale", 18) fun_test_with_default_args() /* woodwhale18 woodwhale19 */
-
方法重载
// 方法重载,重载的方法需要声明,同时满足不同变量(不同的返回值类型) function over_fun_test(params: number): void function over_fun_test(params1: number, params2: string): void function over_fun_test(params: number, params2?:string): void console.log(params,params2) over_fun_test(1) over_fun_test(2,"重载方法") /* 1 undefined 2 重载方法 */
4、接口
在typescript中,规范了类和接口的使用,我们先学习接口的使用
使用关键字interface
来定义接口,两个名字相同的接口会进行合并的操作,实现某个接口的变量需要完善其接口中的每个定义,否则报错
interface Person // 接口
name: string
interface Person // 两个重名的接口是会合并的
readonly age?: number // ? 表示 可选操作符, 表示这个属性在定义的时候可有可无,readonly关键字表示属性是只读的,不可以编辑
interface Person
[propName: string]: any // [propName: string]表示可以自定义填充键,使用any表示值的类型可以是随意的
interface Person
fun(): string // 定义函数
let a: Person =
name: "woodwhale",
age: 19,
test: ,
fun: () =>
return "sheepbotany"
,
console.log(a)
/*
name: 'woodwhale', age: 19, test: , fun: [Function: fun]
*/
使用extends
关键字还可以让接口继承
interface PersonPro extends Person
sex: string
let b: PersonPro =
name: "sheepbotany",
age: 21,
fun()
return "woodwhale"
,
sex: "女"
console.log(b)
/*
name: 'sheepbotany', age: 21, fun: [Function: fun], sex: '女'
*/
5、类
5.1 简单的例子
在typescript完善了js的面向对象的规范,这里直接举一个最简单的例子,编写一个Person类,具有name、age、sex的属性
class Person
name:string
age:number
sex:string
constructor(name:string,age:number,sex:string)
this.name = name
this.age = age
this.sex = sex
let woodwhale = new Person("woodwhale",19,"man")
console.log(woodwhale)
/*
Person name: 'woodwhale', age: 19, sex: 'man'
*/
写完感觉非常像kotlin和java,特别是这个构造函数constructor
但是在typescript也有规定,需要声明属性,如果有没有使用到的属性,需要选择赋予初值
5.2 修饰符
对于每个class的属性,都有属性可以用修饰符修饰
- public 内部外部都可以访问,同时是默认的
- private 私有的,只能在内部使用
- protected 保护的,外部不可访问,内部可以使用,子类可以访问
5.3 父子类
使用关键字extends
和super
关键字完成父子类的构建,和Java一样,就不多说了,举一个例子就懂了
class Person
name:string
age:number
sex:string
constructor(name:string,age:number,sex:string)
this.name = name
this.age = age
this.sex = sex
class Man extends Person
constructor(name:string,age:number)
super(name,age,"man")
5.4 static静态修饰
这个和Java也是一样的,static可以修饰属性,也可以修饰方法
class Person
name:string
age:number
sex:string
constructor(name:string,age:number,sex:string)
this.name = name
this.age = age
this.sex = sex
以上是关于TSTypeScript语法学习的主要内容,如果未能解决你的问题,请参考以下文章