记录了一些常用的ts知识点,也是学习的点滴记录,大佬直接跳过。
类型谓词
类型谓词 类型谓词是一种特殊的返回类型,它向Typescript编译器发出一个特定值是什么类型的信号。类型谓词总是附加到接受单个参数并返回布尔值的函数。类型谓词表示为
argumentName is Type
让我们看个例子
interface Bird {
name: string
age: number
}
interface Fish {
love: string
age: number
}
function getSmallPet(): Bird | Fish {
// ...
return {
love: '小龙虾',
age: 24
}
}
let pet = getSmallPet();
if ((pet as Bird).name) {
console.log((pet as Bird).name)
} else {
console.log((pet as Fish).love);
}
这个例子里, Bird具有一个 name成员。 我们不能确定一个 Bird | Fish类型的变量是否有 name方法。 如果变量在运行时是 Fish类型,那么调用 pet.name就出错了所以我们需要断言(pet as Bird) 告诉代码肯定有这个成员
断言另一种写法
if ((<Bird>pet).name) {
console.log((<Bird>pet).name)
} else {
console.log((<Fish>pet).love);
}
这里可以注意到我们不得不多次使用类型断言。 假若我们一旦检查过类型,就能在之后的每个分支里清楚地知道 pet的类型的话就好了。
TypeScript里的 类型保护机制让它成为了现实。 类型保护就是一些表达式,它们会在运行时检查以确保在某个作用域里的类型。 要定义一个类型保护,我们只要简单地定义一个函数,它的返回值是一个 类型谓词:
function isFish(pet: Fish | Bird): pet is Bird {
return (<Bird>pet).name !== undefined;
}
// 这样调用就都不报错了,简化了类型断言
if (isFish(pet)) {
console.log(pet.name);
} else {
console.log(pet.love)
}
在这个例子里, pet is Fish就是类型谓词。 谓词为 parameterName is Type这种形式, parameterName必须是来自于当前函数签名里的一个参数名。
keyof 和 typeof
keyopf keyof与Object.keys略有相似,只是 keyof 是取 interface 的键,而且 keyof 取到键后会保存为联合类型。
interface iUserInfo {
name: string;
age: number;
}
type keys = keyof iUserInfo;
// 输入内容是 'name' | 'age'
ok,举个例子
我们有这样一个需求,实现一个函数 getValue 取得对象的 value。在未接触 keyof 时,我们一般会这样写:
function getValue(o: object, key: string) {
return o[key];
}
const obj1 = { name: '张三', age: 18 };
const name = getValue(obj1, 'name');
但是这样有2个问题:
- 无法确定返回值类型
- 无法对 key 进行约束,可能会犯拼写的错误也检测不到 这时我们可以使用 keyof 来增强 getValue 函数的类型功能。
function getValue<T extends Object , K extends keyof T>(o: T, key: K): T[K] {
return o[key];
}
const obj1 = { name: '张三', age: 18 };
const a2 = getValue(obj1, 'name');
// 这样getvalue第二个参数只能是name或者age,如果输入其他则会报错
还有另一种写法
这种写法就是控制参数的类型,推荐上面那种泛型方法
function getValue(o: objType, key: keyof objType): objType[keyof objType] {
return o[key];
}
const obj1 = { name: '张三', age: 18, sex: 2 };
type objType = typeof obj1
const a2 = getValue(obj1, 'name');
typeof 在 TypeScript 中,
typeof操作符可以用来获取一个变量或对象的类型。
const sem = { name: "semlinker", age: 30 };
type Sem = typeof sem; // type Sem = { name: string, age:number }
typeof操作符除了可以获取对象的结构类型之外,它也可以用来获取函数对象的类型
function toArray(x: number): Array<number> {
return [x];
}
type Func = typeof toArray; // -> (x: number) => number[]
const断言
TypeScript 3.4 引入了一种新的字面量构造方式,也称为 const 断言。
- 表达式中的任何字面量类型都不应该被扩展;
- 对象字面量的属性,将使用
readonly修饰; - 数组字面量将变成
readonly元组。 下面我们来举一个 const 断言的例子:
let x = "hello" as const;
type X = typeof x; // type X = "hello"
let y = [10, 20] as const;
type Y = typeof y; // type Y = readonly [10, 20]
let z = { text: "hello" } as const;
type Z = typeof z; // let z: { readonly text: "hello"; }
z.text = 'you' // error 只读属性 不可改变
in
in用于取联合类型的值。主要用于数组和对象的构造。
type name = 'firstName' | 'lastName';
type TName = {
[key in name]: string;
};
in还可以结合泛型使用,看下面例子
type Tperson<T> = {
[key in keyof T]: string | number
}
const person = {name: '孙悟空', age: 18, sex: '男'};
const obj:Tperson<typeof person> = {name:'', age:2,sex:''}
泛型工具
Partial<T>
此工具的作用就是将泛型中全部属性变为可选的。
type Animal = {
name: string,
category: string,
age: number,
eat: () => number
}
type PartialAnimal = Partial<Animal>
/**
type PartialAnimal = {
name?: string;
category?: string;
age?: number;
eat?: () => number;
}
*/
const cc:PartialAnimal = { name: '孙悟空' } // 属性全部可选后,可以只赋值部分属性
Pick<T, K>
工具的作用是将 T 类型中的 K 键列表提取出来,生成新的子键值对类型。k就是制定留下来哪些类型
type Animal = {
name: string,
category: string,
age: number,
eat: () => number
}
type BridType = Pick<Animal, "name" | "age">
const bird: BridType = { name: 'bird', age: 1, } // brid只能有name和age属性
Omit<T, K>
正好与Pick相反,它是去除掉某个属性。Pick是留下来某个属性
还是以上面的Animal为例
const OmitAnimal:Omit<Animal, 'name'|'age'> = {
category: 'lion',
eat: () => { return 1 }
} // 必须实现category和eat
Exclude<T, U>
此工具是在 T 类型中,去除 T 类型和 U 类型的交集,返回剩余的部分。
注意这里的 extends 返回的 T 是原来的 T 中和 U 无交集的属性,U属性不会返回,不会返回!!!
type T1 = Exclude<'a' | 'b', 'c' | 'a' | 'd'> // 'b'
type T2 = Exclude<string | number, string> // number
type T3 = Exclude<string, string | number | boolean> // '' 并不会返回U属性
ReturnType<T>
此工具就是获取 T 类型(函数)对应的返回值类型:
type foo = (x: string | number)=> string | number
function func2() {
return '悟空'
}
type fooT = ReturnType<foo> // string | number
type get = ReturnType<typeof func2> // string
Required<T>
此工具可以将类型 T 中所有的属性变为必选项。 举个例子
type person = {
name: string
age?: number
sex?: string
}
const xiaoming:Required<person> = {
name: 'ws',
age: 20,
sex: '男'
}
看上面代码,虽然age和sex属性是可选属性,但是经过Required处理后,变为了必选属性
typescript封装LocalStorage并支持过期时间
enum ts 定义枚举
//字典 Dictionaries expire过期时间key permanent永久不过期
export enum Dictionaries {
expire = '__expire__',
permanent = 'permanent'
}
type ts 定义类型
import { Dictionaries } from "../enum"
export type Key = string //key类型
export type expire = Dictionaries.permanent | number //有效期类型
export interface Data<T> { //格式化data类型
value: T
[Dictionaries.expire]: Dictionaries.expire | number
}
export interface Result<T> { //返回值类型
message: string,
value: T | null
}
export interface StorageCls { //class方法约束
set: <T>(key: Key, value: T, expire: expire) => void
get: <T>(key: Key) => Result<T | null>
remove: (key: Key) => void
clear: () => void
}
index.ts 主要逻辑实现
import { StorageCls, Key, expire, Data,Result } from "./type";
import { Dictionaries } from "./enum";
export class Storage implements StorageCls {
//存储接受 key value 和过期时间 默认永久
public set<T = any>(key: Key, value: T, expire: expire = Dictionaries.permanent) {
//格式化数据
const data = {
value,
[Dictionaries.expire]: expire
}
//存进去
localStorage.setItem(key, JSON.stringify(data))
}
public get<T = any>(key: Key):Result<T | null> {
const value = localStorage.getItem(key)
//读出来的数据是否有效
if (value) {
const obj: Data<T> = JSON.parse(value)
const now = new Date().getTime()
//有效并且是数组类型 并且过期了 进行删除和提示
if (typeof obj[Dictionaries.expire] == 'number' && obj[Dictionaries.expire] < now) {
this.remove(key)
return {
message:`您的${key}已过期`,
value:null
}
}else{
//否则成功返回
return {
message:"成功读取",
value:obj.value
}
}
} else {
//否则key值无效
console.warn('key值无效')
return {
message:`key值无效`,
value:null
}
}
}
//删除某一项
public remove(key:Key) {
localStorage.removeItem(key)
}
//清空所有值
public clear() {
localStorage.clear()
}
}