
大綱
本章主要是一些ts的類型工具以及模塊化和相關(guān)實(shí)踐,涉及以下內(nèi)容:
- 類型編程
- module和namespace
- 小技巧
- ts在react中的實(shí)踐
這篇稍微有點(diǎn)零碎,建議多查閱文檔或者查閱相關(guān)的文章進(jìn)行更多的了解,代碼示例以告知 QAQ
往期推薦:
類型編程
- 索引類型(假定我們要取出如下對象的name屬性對應(yīng)的值)
const user = {
name: 'lili',
age: 20,
sex: 'woman',
}
// 聲明類型
interface User {
[key: string]: any
}
function choose(obj: User, key: string[]): any[] {
return key.map(item => obj[item]) // 返回對應(yīng)屬性的值 返回的是數(shù)組
}
choose(user, ['name'])
- 索引類型查詢操作符
class Person1 {
public name: string = 'lili'
public age: number = 20
}
type getTypePerson = keyof Person1
interface Point {
x: number;
y: number;
}
// type keys = "x" | "y"
type keys = keyof Point;
- 索引訪問操作符 T[K][], 之前也提到過
function Person2<T, K extends keyof T>(obj: T, name: K[]): T[K][] {
return name.map(item => obj[item])
}
const User2 = { name: 'lili', age: 20}
Person2(User2, ['name', 'age'])
// 以下是代碼提示: (相對更加嚴(yán)謹(jǐn))
// (local function) Person2<{
// name: string;
// age: number;
// }, "name" | "age">(obj: {
// name: string;
// age: number;
// }, name: ("name" | "age")[]): (string | number)[]
- 映射類型 [K in keyof T]
interface User3interface {
name: string,
age: number,
}
// 添加每個(gè)都為可選類型
type User3<T> = {
[K in keyof T]?: T[K]
}
type User3s = User3<User3interface>
// 代碼提示:
// type User3s = {
// name?: string | undefined;
// age?: number | undefined;
// }
- 截獲函數(shù)返回值類型 ---- ReturnType
interface User4Interface {
name: string,
age: number,
}
type UserType = () => User4Interface
type User4 = ReturnType<UserType> // User4Interface
- 類型遞歸
interface Other {
hobby: string,
sex: string,
}
interface User5 {
name: string,
age: number,
other: Other
}
// 為每個(gè)類型添加一個(gè)可選類型
// 1. 類型工具 Partial
type U1 = Partial<User5>
// 代碼提示:
// type U1 = {
// name?: string | undefined;
// age?: number | undefined;
// other?: Other | undefined;
// }
// 2. 手動實(shí)現(xiàn)
type Particals<T> = {
[U in keyof T]?: T[U] extends object ? Particals<T[U]> : T[U]
}
type U2 = Particals<User5>
// type U2 = {
// name?: string | undefined;
// age?: number | undefined;
// other?: Particals<Other> | undefined;
// }
- 工具類型
’+‘號 ’-‘號 這兩個(gè)關(guān)鍵字用于映射類型中給屬性添加修飾符,比如-?就代表將可選屬性變?yōu)楸剡x,-readonly代表將只讀屬性變?yōu)榉侵蛔x。比如TS就內(nèi)置了一個(gè)類型工具Required<T>,它的作用是將傳入的屬性變?yōu)楸剡x項(xiàng):
- Required 將傳入的屬性變?yōu)楸剡x項(xiàng)
type Required<T> = { [P in keyof T]-?: T[P] };
- Exclude 的作用是從 T 中排除出可分配給 U的元素. T extends U指T是否可分配給U
type Exclude<T, U> = T extends U ? never : T;
type T = Exclude<1 | 2, 1 | 3> // -> 2
- Omit
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
type Foo = Omit<{name: string, age: number}, 'name'> // -> { age: number }
- Merge Merge<O1, O2>的作用是將兩個(gè)對象的屬性合并:
// type Merge<Obj1, obj2> = Compute<A> + Omit<U, T>
// type obj3 = Merge<obj1, obj2>
type obj1 = {
name: string,
age: number
}
type obj2 = {
sex: string,
hobby?: string,
}
type Compute<A extends any> =
A extends Function
? A
: { [K in keyof A]: A[K] }
type obj3 = Compute<obj1 & obj2>
// type obj3 = {
// name: string;
// age: number;
// sex: string;
// hobby?: string | undefined;
// }
- Intersection Intersection是Extract與Pick的結(jié)合,Intersection<T, U> = Extract<T, U> + Pick<T, U>
type obj4 = {
name: string,
age: number,
}
type obj5 = {
name: string,
sex: string,
}
type Intersection<T extends object, U extends object> = Pick<T, Extract<keyof T, keyof U> & Extract<keyof U, keyof T>> // Extract 提取
type obj6 = Intersection<obj4, obj5>
// type obj6 = {
// name: string;
// }
- Overwrite<T, U>顧名思義,是用U的屬性覆蓋T的相同屬性.
type obj7 = {
name: string,
age: number,
}
type obj8 = {
name: number,
}
// import { Diff } from 'utility-types' 要安裝一下庫
type Overwrite<T extends object, U extends object, I = Diff<T, U> & Intersection<U, T>> = Pick<I, keyof I>
type obj9 = Overwrite<obj7, obj8>
// type obj9 = {
// name: number; --- 被重寫了
// age: number;
// }
// Mutable 將 T 的所有屬性的 readonly 移除
type Mutable<T> = {
-readonly [P in keyof T]: T[P]
}
type ob = {
readonly name: string,
age: number,
}
type obj10 = Mutable<ob>
// type obj10 = {
// name: string;
// age: number;
// }
module和namespace
全局變量
比如在1.ts定義:const a = 1, 2.ts定義: const a = 2 這樣全局中定義的變量會報(bào)錯(cuò) 因?yàn)橹貜?fù)聲明了 避免全局變量導(dǎo)出類型
export type User = {
name: string,
age: number,
}
- 導(dǎo)出多個(gè)類型
// 導(dǎo)出多個(gè)類型
type User1 = {
name: string,
age: number,
}
interface User2 {
name: string,
age: number,
}
// "isolatedModules": false, tsconfig.json 要設(shè)置一下
export { User1, User2 }
- 重命名
export { User1 as user1 }
- 引入
import { User2 as user2 } from './module';
// 整體導(dǎo)入
import * as u from './module';
// 同樣的 --- 默認(rèn)導(dǎo)出
export default () => {
}
- namespace
其實(shí)一個(gè)命名空間本質(zhì)上一個(gè)對象,它的作用是將一系列相關(guān)的全局變量組織到一個(gè)對象的屬性
如果一個(gè)命名空間在一個(gè)單獨(dú)的 TypeScript 文件中,則應(yīng)使用三斜杠 /// 引用它,語法格式如下:
// index.ts
// 聲明全局的明明空間
declare namespace USER {
// 導(dǎo)出接口
export interface find { (name: string): string }
export interface create { (name: string): string }
export interface update { (name: string): string }
export interface deleted { (name: string): string }
}
// 引入文件
/// <reference path = "index.ts" />
// 使用命名空間的模塊
interface API {
USER: {
update: USER.update
// .....
},
}
小技巧
- 注釋,利于智能提示快速定位代碼
interface User {
/**
* 用戶
*/
name: string,
age: number,
}
const user: User = { name: 'lili', age: 20 }
// 以下是代碼提示
// (property) User.name: string
// 用戶
- 類型推導(dǎo)
function getUser(name: string): string {
return name
}
// typeof 獲取整體函數(shù)的類型
type getU = typeof getUser
// type getU = (name: string) => string
// h獲取返回值的類型
type returnT = ReturnType<typeof getUser>
// type returnT = string
- 巧用Omit
有時(shí)候我們需要復(fù)用一個(gè)類型,但是又不需要此類型內(nèi)的全部屬性,因此需要剔除某些屬性,這個(gè)時(shí)候 Omit 就派上用場了。
interface User1 {
name: string,
age: number,
sex: string,
}
type newUser1 = Omit<User1, 'sex'>
// type newUser1 = {
// name: string;
// age: number;
// }
- Record 高級類型
Record 允許從 Union 類型中創(chuàng)建新類型,Union 類型中的值用作新類型的屬性。有利于類型安全
type List = 'u1' | 'u2' | 'u3'
// 要求用戶表的屬性必須包含 { name: string, age: number } 類型字段
type UserList = Record<List, { name: string, age: number }>
const userList: UserList = {
u1: { name: 'lili', age: 20 },
u2: { name: 'xiaoming', age: 21 },
u3: { name: 'xiaohong', age: 22 },
}
react實(shí)踐
- 編寫一個(gè)無狀態(tài)的組件
寫法1:
// 定義一個(gè)接口
interface Rrop {
/**
* 這是一個(gè)react組件的屬性
*/
name: string,
age: number,
}
// 無狀態(tài)組件
export const comp: React.SFC<Rrop> = props => {
const { name, age } = props
return (
<div>name: {name} age: {age}</div>
)
}
寫法2:
type Props1 = {
click(e: React.MouseEvent<HTMLElement>): void
children?: React.ReactNode
}
const handleClick = () => console.log('click')
const Events = ({ click: handleClick}: Props1) => {
<div onClick={handleClick}></div>
}
- 編寫狀態(tài)組件
避免狀態(tài)被顯示改變 所以 需要賦 readonly
const initialState = {
name: 'lili',
age: 20
}
type States = Readonly<typeof initialState>
export class InitialComp extends React.Component {
// 再次只讀
public readonly state: States = initialState
render() {
return (
<div>hello</div>
)
}
}
- ref
interface Props {
name: string,
age: number,
}
interface State {
name: string,
}
export class StateComp extends React.Component<Props, State> {
private inputRef = React.createRef<HTMLInputElement>() // 創(chuàng)建ref div 組件的話那么這個(gè)類型就是 HTMLDivElement。
constructor(props: Props) {
super(props)
this.state = { // (property) React.Component<Props, State, any>.state: Readonly<State> 組件自動為我們分配的
name: 'lili'
}
}
private setStat(val: string) {
this.setState({ name: val })
}
// onChange事件
private onChangeInput(e: React.ChangeEvent<HTMLInputElement>) {
this.setState({ name: e.target.value })
}
// form表單事件
private handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault()
}
render() {
return (
<>
<div>{this.state.name}</div>
<input ref={this.inputRef} onChange={e => this.onChangeInput(e)}/>
</>
)
}
}
- 默認(rèn)屬性傳遞
interface Other {
hobby? : string
}
class ClassProp {
public name: string = ''
public submit = (name: string): string => name
public other: Other = {
hobby: ''
}
}
// 實(shí)例化類傳遞 默認(rèn)屬性
export class PropsClass extends React.Component<ClassProp, State> {
// 1. 可以減少代碼量
// 2. 減少出錯(cuò)率
public static defaultProps = new ClassProp()
public render() {
const { name, other } = this.props
// 如果遇到屬性找不到可以三木運(yùn)算符判斷下或者是 other!.hobby
return (
<div>{ name } { other.hobby}</div>
)
}
}
- promise類型問題
// promise類型問題
interface propP<T> {
name: string,
age: number,
classes: T,
}
export class PromiseComp extends React.Component {
// 返回promise對象類型
public async getData(name: string): Promise<propP<string[]>> { // 表示返回的res的參數(shù)類型
return {
name: 'lili',
age: 20,
classes: ['class1','clas2'],
}
}
public request() {
this.getData('lili').then(res => {
console.log(res)
})
}
}
到此,系列文章基本完結(jié)啦~ 近期也在整理一些 ts 實(shí)踐性的文章,主要以react框架為主,過段時(shí)間會陸續(xù)上傳,如果對大家有幫助記得點(diǎn)個(gè)贊~ , 如有錯(cuò)誤請指正, 我們一起解決,一起進(jìn)步。