完整的声明格式如下:
声明了类型后TypeScript就会进行类型检测,声明的类型可以称之为类型注解;
var/Iet/const标识符:数据类型=赋值;
(ps:在tslint中并不推荐使用var来声明变量,主要原因和ES6升级后let和var的区别是一样的,var没块级作用域会引起很多的问题)
数据类型是小写:
//string:TypeScript中的字符串类型
//String:JavaScript的字符串包装类的类型
我们并不会在声明每一个变量时都写上对应的类型注解,我们更希望可以通过TypeScript本身的特性帮助我们推断出对应的变量类型:
当声明和初始化是在同一行可以省略变量类型的声明,ts内部会进行一个判断:
let变量名=值;
相当于
let变量名:变量类型=值;
这三者和js一样,分开浅说:
数字类型和JavaScript一样,不区分int和double,统一为number类型。(当然可以加上前缀表示进制数)
boolean没什么可说的,t/f,赋值可以表达式,比如6>7这种
string可以使用单引号或者双引号,当然也支持模板字符串
const info = my name is ${name},age is ${age},height is ${height];
这三者也是ts js都有的,但语法稍有不同
Array类型
不写类型会类型推断
Array后加<泛型>
更推荐第一种写法,第二种在jsx中可能会出错
如果添加其他类型到数组中会报错
object 类型
建议直接写不添加类型注解,如果添加object类型注解后那么就不能从这个对象取属性或者赋值,会报错
null和undefined类型
在 JavaScript 中,undefined 和 null 是两个基本数据类型。
在TypeScript中,它们各自的类型也是undefined和null,也就意味着它们既是实际的值,也是自己的类型。
直接赋值两者的类型推断都是any。
这是es6新增类型,我们可以通过symbol来定义相同的名称,因为Symbol函数返回的是不同的值
在某些情况下我们确实无法确定一个变量的类型,并且可能它会发生一些变化,这个时候我们可以使用any类型;
我们可以对any类型的变量进行任何的操作,包括获取不存在的属性、方法(比如对一个对象使用split方法)
用于描述类型不确定的变量,和any相似,主要区别在于:
unknown类型只能赋值给any和unknown类型
any类型可以厨值给任意类型,
防止拿到一个不确定值后乱用
void通常用来指定一个函数是没有返回值的,那么它的返回值就是void类型
never 表示永远不会发生值的类型
如果一个函数中是一个死循环或者抛出一个异常,那么这个函数会返回东西吗?
不会,那么写void类型或者其他类型作为返回值类型都不合适,我们就可以使用never类型
//可以越界添加元素(不建议),但不可越界访问
const list: [string, number] = ['age', 18]
list.push('hello world')
console.log(list) // [ 'age', 18, 'hello world' ]
console.log(list[2]) // Tuple type '[string, number]' of length '2' has no element at index '2'
可选元素类型
let list: [number, string?, boolean?]
list = [10, 'name', true]
list = [10, 'name']
list = [10]
可选元素必须在必选元素的后面,也就是如果一个元素后缀了 ?号,其后的所有元素都要后缀 ?号:
let list1: [number, string?, boolean]
// Error: A required element cannot follow an optional element
场景:
React Hook 的 useState
tuple和数组的区别?
首先,数组中通常建议存放相同类型的元素,不同类型的元素不推荐放在数组中。(可以放在对象或者元组中)
其次,元组中每个元素都有自己特性的类型,根据索引值获取到的值可以确定对应的类型;
TypeScript允许我们指定函数的参数和返回值的类型
在开发中,通常情况下可以不写返回值的类型(自动推导)
对于匿名函数:
item根据上下文的环境推导出来的,这个时候可以不添加的类型注解
上下文中的函数:可以不添加类型注解
没有指定item的类型,但是item是一个string类型:
这是因为TypeScript会根据forEach函数的类型以及数组的类型推断出item的类型;
这个过程称之为上下文类型( contextual typing ),因为函数执行的上下文可以帮助确定参数和返回值的类型;
希望限定一个函数接受的参数是一个对象,我们可以使用对象类型
属性之间可以使用 , 或者 ; 来分割,最后一个分隔符是可选的;
每个属性的类型部分也是可选的,如果不指定,那么就是any类型
联合类型是由两个或者多个其他类型组成的类型,表示可以是这些类型中的任何一个值;
在使用过程中常常需要缩小联合,TypeScript可以根据我们缩小的代码结构,推断出更加具体的类型
有时候TypeScript无法获取具体的类型信息,这个我们需要使用类型断言。
TypeScript只允许类型断言转换为 更具体 或者 不太具体(unknown/any) 的类型版本
class Person{
}
class Student extends Person{
studying(){
}
}
function sayHello(p:Person){
(p as Student).studying()
)
const stu = new Student()
sayHello(stu)
as unknown/any as其他类型
表示可以确定某个标识符是有值的
(下图方法不加!编译阶段直接报错)
事实上并不是TypeScript独有的特性,它是ES11(ES2020)中增加的特性
它的作用是当对象的属性不存在时,后面代码不再执行直接返回undefined;如果存在,会继续执行
//不可用!替代,因为如果没有friend运行阶段会报错
//没传friend
console.log(info.friend?.name) //undefined
??
是ES11增加的新特性;
空值合并操作符(??)是一个逻辑操作符,当操作符的左侧是 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。一般用于给默认值,类似||
321
!!
将一个其他类型转换成boolean类型,类似于Boolean(变量)的方式;
字面量类型
类型只能与值相等
const赋值时类型默认就是字面量类型
下图重新赋值报错:
默认情况下这么做是没有太大的意义的,但是我们可以将多个类型联合在一起
存在如下安全隐患,info.method被推理成string类型,也就是能被修改成任意字符串,进而有可能不符合字面量的约束,也就是我们没办法将一个string 赋值给一个字面量类型,因此会报错
法一:
info.method as Method //Method已经type可选GET或者POST
法二:
写的时候就规定好对象内属性类型
type Request ={
url:string;
method:'GET'|'POST'
}
const options: Request={
url:'www.',
method:"POST"
}
function request(url:string,method:'GET'|'POST'){
}
request(options.url,options.method)
export{}
法三:
字面量推理
此时url 和 method的类型都成了后面所被赋予的字面量类型
type Request ={
url:string;
method:'GET'|'POST'
}
const options={
url:'www.',
method:"POST"
}as const
function request(url:string,method:'GET'|'POST'){
}
request(options.url,options.method)
export{}
指路 TS学习笔记(三)