函数 和 对象
函数是javaScript中重要的组成部分, typescript为函数提供了参数类型和返回值类型, 允许我们指定在声明函数参数时, 可以在每个参数后面添加类型注解
function adny(msg: string) {
return msg + 'hello'
}
console.log(adny('erkelost'));
adny(123)
我们也可以添加返回值的类型注解,这个注解在函数的参数列表的后面, 和声明变量注解一样 我们通常情况下不需要返回类型注解 因为typescript会根据返回值的类型自动推断类型注解
function add(num1: number, num2: number): number {
return num1 + num2
}
通常情况下 我们在定义一个函数时 ,都会给函数的参数添加上类型注解
function send(msg: string, num: number){}
但是我们如果能根据上下文环境,推断出来这个参数的类型,那么我们可以不添加类型注解
const arr: string[] = ['adny', 'erkelost']
arr.forEach(item => console.log(item))
我们并没有指定item 的类型 但是item 是一个 string 类型 这是因为typescript 会根据foreach函数类型和 数组的string类型 推断出item的类型 这个过程称之为 上下文类型 可以帮助我们确定参数 和返回值类型
如果我们希望函数的参数是一个对象类型
我们可以使用一个对象类型 在对象中 我们可以添加属性告知 typescript 我们需要的是什么参数类型 属性之间可以用, : 分割 如果我们不指定类型 那么就是 any类型
function setInfo(obj: {name:string ; age: number}) {
console.log(obj.name);
console.log(obj.age);
}
function setInfo(obj: {name:string , age: number}) {
console.log(obj.name);
console.log(obj.age);
}
function setInfo(obj: {name:string; age}) {
console.log(obj.name);
console.log(obj.age);
}
对象属性也可以添加 指定 那些属性是可选的 用?:添加
function add (data: {a: number, b: number, c?: number}) {
return data.a + data.b + data.c
}
console.log(add({a:10, b:20, c:30}));
因为可能属性c为可选类型 可能值为undefined 在typescript会报错
function add (data: {a: number, b: number, c?: number}) {
}
console.log(add({a:10, b:20, c:30}));
所以我们可以 判断c是否存在 值不为undefined的情况下
function add (data: {a: number, b: number, c?: number}) {
if (data.c) {
return data.a + data.b + data.c
}
}
console.log(add({a:10, b:20, c:30}));
可选类型 可以看做是定义类型 和 undeifined 类型结合的联合类型 我们可以给参数传递undeifined
function say(msg?: string) {
console.log(msg);
}
say('hello')
say(undefined)
say(null)
typescript中允许我们使用运算符在构建新类型 联合类型 就是 由两个 或者多个类型组成的新类型 表示类型可以是其中的任何一个值
function getInfo(name: number | string) {
console.log(name);
}
getInfo('123')
getInfo(123)
getInfo(false)
那么我们如何使用联合类型呢 我们可以使用缩小联合类型 来处理 缩小代码结构 推断出更加准确的类型
function getInfo(name: number | string | null) {
if (typeof name === 'string') {
console.log(name.toUpperCase())
} else if (typeof name === 'number') {
console.log(name.toFixed(2));
} else {
console.log(name);
}
}
getInfo(123.99999)
getInfo('adb')
getInfo(null)
使用typeof 来帮助我们确定类型
在我们给对象类型和联合类型命名时, 如果我们要在多个地方使用 就要编写多次 所以我们可以给类型起一个别名
type nameType = number | string | null
function getInfo(name: nameType) {
if (typeof name === 'string') {
console.log(name.toUpperCase())
} else if (typeof name === 'number') {
console.log(name.toFixed(2));
} else {
console.log(name);
}
}
getInfo(123.99999)
getInfo('adb')
getInfo(null)
type addType = {
a: number,
b: number,
c?: number
}
function add (data: addType) {
if (data.c) {
return data.a + data.b + data.c
}
}
console.log(add({a:10, b:20, c:30}));
类型断言(Type Assertion)可以用来手动指定一个值的类型。
有时候typescript 无法准确地获得一个值的类型 我们可以手动来获取 就需要使用类型断言
const img = document.getElementById('#app')
img.src = 'https://wallhaven.cc/'
为了 让我们img 能够得到具体的类型 来获得相应的属性 我们可以使用类型断言
const img = document.getElementById('#app') as HTMLImageElement
img.src = 'https://wallhaven.cc/'
typescript 只允许类型断言转换为 更具体 或者不具体的类型版本 来防止强制转换
const name: string = 'erkelost' as number
上一篇我们可以知道 任何类型都可以是unknown类型 但是 unknown类型只能被赋值给any 类型 和 unknown 类型
const name = ('erkelost' as unknown) as number
这样我们 是不能在前面给name 声明类型 否则会报错
在我们前面讲到的 可选类型 也就是 类型 和 undefined 结合的联合类型
function getName(name?: string) {
console.log(name.toUpperCase());
}
getName('erke')
但是如果我们确定我们传入的参数是有效的 那么我们就可以使用非空类型断言
function getName(name?: string) {
console.log(name!.toUpperCase());
}
getName('erke')
非空类型断言使用的是! 表示我们确定某个标识符是有值的 这样我们就可以跳过typescript对我们的监测
如果当对象属性不存在时 就会短路 报错 undefined 我们在定义类型的时候 只要type里面的 都要和 我们的对象 属性一一对应 可选链属性 是 ES11 中添加的属性 Typescript 中可以使用
我们可以使用?. 的操作符 他的作用是当对象的属性不存在是 就会短路 返回 undefined
type objType = {
name: string,
age: number,
obj: {
name: string,
age: number
}
}
const info: objType = {
name: 'erkelost',
age: 9999999
}
type objType = {
name: string,
age: number,
obj?: {
name: string,
age: number
}
}
const info: objType = {
name: 'erkelost',
age: 9999999
}
console.log(info.name);
console.log(info.obj?.name);
!! 是 把一个类型转换成boolean类型
?? 是 逻辑操作符当操作符的左侧是null 或者 undefined 的时候 返回右侧操作数 否则返回左侧的
const a: string = 'erkelsot'
console.log(!!a);
const erke = undefined
console.log(erke ?? 'adny');
除了我们上述类型 之外 还有 一个字面量类型 字面意思 就是 把我们赋值 当成 类型
const message: "Hello World" = "Hello World"
我们可以默认在函数中 将多个类型联合在一起
type styleType = 'bottom' | 'padding' | 'align'
function changeStyle(style: styleType) {
console.log(`样式${style}`);
}
changeStyle('bottom')
changeStyle('padding')
changeStyle('align')
changeStyle('border')
const options = {
url: "https://wallhaven.cc/",
method: "POST"
}
type Methods = 'GET' | 'POST'
function request(url?: string, method?: Methods) {
console.log(url, method);
}
request(options.url, options.method)
我们只能传递Methods类型中的字符串类型 而不能随便传递一个随意的字符串 这样会有安全隐患
因为我们的options.method 是string 类型 我们函数 参数类型是 Methods 类型 如果我们options.method是一个 字符串123 那么 我们本来只能传递get 和 post 字符串 这样就会报错
1. 第一种方法 我们可以限定options 的类型 这样就能防止 传递别的字符串
type Request = {
url: string,
method: Methods
}
const options: Request = {
url: "https://wallhaven.cc/",
method: "POST"
}
type Methods = 'GET' | 'POST'
function request(url?: string, method?: Methods) {
console.log(url, method);
}
request(options.url, options.method)
2. 第二种方法 如果我们能够确定我们的对象属性字符串确实 传递正确后 我们可以 使用类型断言 把一个宽泛的类型转换成一个具体的类型 来使用 消除安全隐患 主要是 我们的字符串 只能填 get 和 post 具有安全隐患
const options = {
url: "https://wallhaven.cc/",
method: "POST"
}
type Methods = 'GET' | 'POST'
function request(url?: string, method?: Methods) {
console.log(url, method);
}
request(options.url, options.method as Methods)
-
3. 第三种方法 字面量推理 在给我们传递的对象后面 添加 一个 as const 变成一个只读对象 就可以确定我们传递的参数如果 就是一个 get 或者 post 他就能确定 我们使用的 字符串 就是这两个
const options = {
url: "https://wallhaven.cc/",
method: "POST"
} as const
const options: {
readonly url: "https://wallhaven.cc/";
readonly method: "POST";
}
这样我们拿到的这个对象是一个只读类型 就可以确定 他的值 只能是 post 不可以修改 把一个比较宽泛的类型 转换成了一个具体的一个值 字面量的类型