欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

TypeScript類(lèi)型操作之字符串處理功能詳解

 更新時(shí)間:2023年07月27日 14:02:17   作者:小烏龜快跑  
這篇文章主要為大家介紹了TypeScript類(lèi)型操作之字符串處理功能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

本文主要介紹模板 TypeScript 對(duì)模板字符串的能力支持及實(shí)現(xiàn)原理,深入介紹了 TypeScript 提供的字符串操作能力。結(jié)合《TypeScript玩轉(zhuǎn)類(lèi)型操作之基礎(chǔ)篇》內(nèi)容,完整覆蓋了TS體操的能力基礎(chǔ)。附帶一步步實(shí)現(xiàn)將 aa_bb___cc 轉(zhuǎn)換成 aaBbCc 的類(lèi)型實(shí)現(xiàn)技巧。

模板字符串

模板字符串是 JS 語(yǔ)言提供了使用反引號(hào) ` 分割的字面量,支持多行字符、嵌入字符串插值表達(dá)式以及附帶標(biāo)簽(與標(biāo)簽函數(shù)異同使用)。

let str = `user name is : ${name}`; // 插值表達(dá)式
let str2 = `
line1....
line2....
` ; // 多行字符
function str3Tag(all, ...expresitons) {
  console.log(all, expresitons); 
  return all
}
const name = 'tony';
const age = 11;
str3Tag`hello name is: ${str}, age is ${age}`)
// all: ['hello name is: ', ', age is ', '', raw: Array(3)]
//expressions: Array(0) (2) ['name', 11]

模板字符串在JS中的應(yīng)用不是本文我們的重點(diǎn),如果大家想深入了解一下可以先看看MDN然后再翻翻ECMAScript的規(guī)范基本上就很深入了。主要是介紹在 TypeScript 中,支持了哪些特性,提供了什么能力。

TS 中模板字符串的相關(guān)特性

當(dāng)模板字符串插值表達(dá)式用于類(lèi)型位置時(shí),具有以下特性:計(jì)算出來(lái)的模板字符串值會(huì)作為一個(gè)字符串固定類(lèi)型、如果插值表達(dá)式是一個(gè)聯(lián)合類(lèi)型那么將得到一個(gè)新的聯(lián)合類(lèi)型成員是插值聯(lián)合類(lèi)型成員與模板字符串靜態(tài)部分生成字符串并集。

構(gòu)造新的類(lèi)型

普通插值表達(dá)式,構(gòu)造一個(gè)復(fù)合型的字符串類(lèi)型。

type World = `world`;
type Greeting = `hello ${World}`;
// type Greeting = "hello world";

在插值位置使用聯(lián)合類(lèi)型時(shí),構(gòu)造出一個(gè)新的字符串聯(lián)合類(lèi)型。

type EmailLocaleIDs = "welcome_email" | "email_heading";
type FooterLocaleIDs = "footer_title" | "footer_sendoff";
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;
/*
type AllLocaleIDs = 
  | "welcome_email_id" 
  | "email_heading_id" 
  | "footer_title_id" 
  | "footer_sendoff_id"
*/
// 換個(gè)位置構(gòu)造
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;
type Lang = "en" | "ja" | "pt";
type LocaleMessageIDs = `${Lang}_${AllLocaleIDs}`;
/*
type LocaleMessageIDs = 
    | "ch_welcome_email_id" 
     | "ch_email_heading_id" 
  | "ch_footer_title_id" 
  | "ch_footer_sendoff_id" 
  | "en_welcome_email_id" 
  | "en_email_heading_id" 
  | "en_footer_title_id" 
  | "en_footer_sendoff_id" 
  | "jp_welcome_email_id" 
  | "jp_email_heading_id" 
  | "jp_footer_title_id" 
  | "jp_footer_sendoff_id"
*/

TS 會(huì)動(dòng)態(tài)遍歷插值中的聯(lián)合類(lèi)型,然后構(gòu)造出所有情況下組合出來(lái)的并集聯(lián)合類(lèi)型。這在我們項(xiàng)目中組合出新的類(lèi)型挺實(shí)用。

使用模板字符串進(jìn)行推理

基于對(duì)象類(lèi)型內(nèi)部屬性名構(gòu)造字符串類(lèi)型,然后根據(jù)對(duì)象類(lèi)型中對(duì)應(yīng)的屬性值類(lèi)型進(jìn)行推導(dǎo)新的類(lèi)型。功能會(huì)很強(qiáng)大。我們以一個(gè)案例進(jìn)行解釋:題目是對(duì)一個(gè)對(duì)象進(jìn)行代理,代理后需要監(jiān)聽(tīng)到這個(gè)對(duì)象的變化事件,現(xiàn)在需要定義一套類(lèi)型來(lái)實(shí)現(xiàn)這個(gè)功能。

簡(jiǎn)化的JS代碼如下:

const tonyDefaultInfo = {
  name: 'tony',
  age: 11,
};
function makeWatchedObject(target) {
  // 代理處理 ... 
  return target;
}
const tony = makeWatchedObject(tonyDefaultInfo);
tony.on('nameChanged', (newValue) => {
    console.log(newValue);
});

現(xiàn)在我們需要使用類(lèi)型來(lái)對(duì) 調(diào)用 on 上注冊(cè)的事件名稱做檢查:要求on監(jiān)聽(tīng)的屬性名稱必須滿足(屬性名+ 'Changed' ) 格式,監(jiān)聽(tīng)函數(shù)返回值類(lèi)型和原對(duì)象一致【監(jiān)聽(tīng)name,返回值類(lèi)型是 string、監(jiān)聽(tīng)age返回值類(lèi)型是number】。我們分三步實(shí)現(xiàn)一下這個(gè)類(lèi)型的定義。

第一步:如何修飾 makeWatchedObject 函數(shù)的類(lèi)型,定義其返回值類(lèi)型為傳入的值類(lèi)型。

declare function makeWatchedObject<Type>(obj: Type): Type & { on(eventName: string, callback:(newValue: any)=>void):void };

第二步:定義一個(gè)類(lèi)型工具,負(fù)責(zé)提取類(lèi)型上的屬性作為模板字符串的插值。大家不清楚 extends 、 keyof 用法的請(qǐng)看這篇文章 《TypeScript 玩轉(zhuǎn)類(lèi)型操作之基礎(chǔ)篇》,里面詳細(xì)介紹了其使用場(chǎng)景以及方式,包含與 typeof、infer 等關(guān)鍵詞的配合使用以及Omit等高級(jí)類(lèi)型的源碼解析。

type PickPropertyNameComposeChange<T extends {[k:string]:any}> = {
  [K in keyof T]: `${K}Changed`;
}
type Person = {
  name: string;
  age: number
}
type ChangeKeys = PickPropertyNameComposeChange<Person>
/*
type ChangeKeys = {
    name: "nameChanged";
    age: "ageChanged";
}
*/

第三步:將屬性名提取封裝成字符串用于on函數(shù)參數(shù)的修飾, 并提取目標(biāo)類(lèi)型上的值類(lèi)型作為callback參數(shù)的類(lèi)型。

// 定義一個(gè)工具類(lèi)型,特殊處理定義一個(gè) on 函數(shù)的類(lèi)型,主要是修飾 on 的參數(shù)類(lèi)型
type PropertiesEventChange<T> = {
  on<K extends string & keyof T >(eventName: `${K}Changed`, callback: (newValue:T[K]) => void):void
}
declare function makeWatchedObject<Type>(obj: Type): Type & PropertiesEventChange<Type>;
const p = makeWatchedObject({
  name: 'tony',
  age: 11
});
p.on('ageChanged', (age) => age);
// (method) on<"age">(eventName: "ageChanged", callback: (newValue: number) => void): void

模板字符串的解析原理

TypeScript 在編譯過(guò)程中,編譯器會(huì)將代碼解析成 AST (抽象語(yǔ)法樹(shù))。對(duì)于模板字符串編譯器會(huì)識(shí)別出模板字符串的靜態(tài)部分(普通的字符文本)和動(dòng)態(tài)部分(插值表達(dá)式)解析的結(jié)果仍然是AST結(jié)構(gòu),完成解析以后TypeScript 會(huì)進(jìn)行類(lèi)型推導(dǎo)。類(lèi)型推導(dǎo)時(shí)編譯器會(huì)分析每個(gè)插值表達(dá)式的類(lèi)型,根據(jù)類(lèi)型不同進(jìn)行轉(zhuǎn)換推導(dǎo)出整個(gè)模板字符串的類(lèi)型。這里會(huì)有類(lèi)似于 JavaScript 類(lèi)型轉(zhuǎn)換的場(chǎng)景非字符如何 toPrimitive 。

TS代碼:

const name = 'Alice';
const age = 30;
const message = `Hello, my name is ${name} and I am ${age} years old.`;

解析成類(lèi)似AST語(yǔ)法樹(shù):

TemplateLiteral
└── Quasi (Hello, my name is )
└── Expression (name)
└── Quasi ( and I am )
└── Expression (age)
└── Quasi ( years old.)

解析模板字符串的結(jié)構(gòu),然后根據(jù)插值表達(dá)式的類(lèi)型推導(dǎo)出整個(gè)模板字符串的類(lèi)型。

字符串操作工具類(lèi)型【有的說(shuō)是高級(jí)類(lèi)型】

TypeScript 為了提升對(duì)字符串的操作能力(大小寫(xiě)轉(zhuǎn)換、首字母大小寫(xiě)轉(zhuǎn)換),內(nèi)置封裝了四個(gè)主要的工具類(lèi)型。分別是 Uppercase<StringType>、Lowercase<StringType>、Capitalize<StringType>、Uncapitalize<StringType> 這些類(lèi)型并不是像 Omit、Record 等高級(jí)類(lèi)型在 type.d.ts 中自定義封裝的,Typescript 為了性能將其內(nèi)置在編譯器中實(shí)現(xiàn)【源碼實(shí)在沒(méi)看明白,抱歉了諸位】。

我們來(lái)分別看看他們的功能:

Uppercase<StringType>

將字符串中的每個(gè)字母都轉(zhuǎn)換成大寫(xiě)。

type Greeting = "Hello, world"
type ShoutyGreeting = Uppercase<Greeting>
//type ShoutyGreeting = "HELLO, WORLD"

我們來(lái)實(shí)現(xiàn)這樣一個(gè)簡(jiǎn)單的題目:將一個(gè)對(duì)象上的所有屬性名提取出來(lái),并轉(zhuǎn)成大寫(xiě)。

// 限制一下K從T的屬性中提取,并且是string類(lèi)型
type PickPropertyToUppercase<T, K extends string & keyof T> = Uppercase<K>;
const per = {
  name: 'tony',
  age: 11,
}
type PerType = PickPropertyToUppercase<typeof per, keyof typeof per>
// type PerType = "NAME" | "AGE"
// 如果你想只有一個(gè)入口,也可以這樣再封一個(gè)自定義的類(lèi)型工具
type A<T extends { [k: string ]: any }> = PickPropertyToUppercase<T, keyof T>;
type APerType = A<typeof per>
//type APerType = "NAME" | "AGE"

這些基礎(chǔ)能力結(jié)合我們上一篇文章中的類(lèi)型基礎(chǔ)【keyof、 typeof、infer、extends、條件類(lèi)型~】就是我們玩轉(zhuǎn)體操的基礎(chǔ)啦~

Lowercase<StringType>

將字符串中所有的字母都變成小寫(xiě),和 Uppercase 用法是類(lèi)似的。

type Greeting = "Hello, world"
type QuietGreeting = Lowercase<Greeting>
// type QuietGreeting = "hello, world"

Capitalize<StringType>、Uncapitalize<StringType>

將字符中的首字母大寫(xiě)首字母小寫(xiě)大家一看也都懂,我們來(lái)寫(xiě)一個(gè)實(shí)現(xiàn)一個(gè)題目:下劃線命名轉(zhuǎn)小駝峰的命名方式。

比如: aa_bb_cc 轉(zhuǎn)換成 aaBbCc 。

實(shí)現(xiàn)思路:利用條件類(lèi)型進(jìn)行檢查,將字符串按照 _ 下劃線進(jìn)行分割,然后下劃線前后部分進(jìn)行首字母大寫(xiě),最后再將結(jié)果進(jìn)行首字母小寫(xiě)。

第一步:剔除下劃線,利用條件類(lèi)型提取 _ 下劃線分割的前后兩個(gè)部分,然后組合出新的字符串。

type RemoveBaseline<T extends string>T extends `${infer FirstStr}_${infer LastStr}` ? `${FirstStr}${LastStr}` : T;
type NotBaselineStr = RemoveBaseline<"aa_bb">
// type NotBaselineStr = "aabb"

第二步:在第一步的基礎(chǔ)上將 FirstStr、LastStr 首字母大寫(xiě)進(jìn)行組合。

type UpperCamel<T extends string> T extends `${infer FirstStr}_${infer LastStr}` ? `${Capitalize<FirstStr>}${Capitalize<LastStr>}` : T;
type Camelstr = UpperCamel<"aa_bb">
// type Camelstr = "AaBb"

第三步: 步驟二的結(jié)果只能實(shí)現(xiàn)第一個(gè)_下劃線的轉(zhuǎn)換,需要將字符串中所有的下劃線進(jìn)行轉(zhuǎn)換需要加上遞歸處理【分別_分開(kāi)的字符串進(jìn)行左右遞歸】,將所有的 _ 下劃線剔除。 最后將結(jié)果進(jìn)行首字母大寫(xiě),即可上菜。

type UpperCamel<T extends string> T extends `${infer FirstStr}_${infer LastStr}` ? `${Capitalize<UpperCamel<FirstStr>>}${Capitalize<UpperCamel<LastStr>>}` : T;
type Camelstr = UpperCamel<"aa_bb_cc___dd">
//type Camelstr = "AaBbCcDd"
// 再將 AaBbCcDd -> aaBbCcDd 這個(gè)方式就很簡(jiǎn)單了 直接調(diào)用一次 Uncapitalize 
type LowerCamel<T extends string> = Uncapitalize<UpperCamel<T>>;
type lowerCamelStr = LowerCamel<"aa_bb_cc___dd">
// type lowerCamelStr = "aaBbCcDd"

至此,字符串的類(lèi)型操作以及模板字符串中的相關(guān)技術(shù)點(diǎn)就介紹完了。結(jié)合《TypeScript 玩轉(zhuǎn)類(lèi)型操作之基礎(chǔ)篇》我們體操的能力已經(jīng)具備,下一篇我們搞幾個(gè)面試中經(jīng)常被問(wèn)到的TS體操操作,練練手。歡迎大家評(píng)論區(qū)推薦一下。

參考資料

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Refer...

https://www.typescriptlang.org/docs/handbook/2/template-liter...

http://www.dbjr.com.cn/javascript/293208369.htm

以上就是TypeScript類(lèi)型操作之字符串處理功能詳解的詳細(xì)內(nèi)容,更多關(guān)于TypeScript類(lèi)型操作字符串處理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • xterm.js在web端實(shí)現(xiàn)Terminal示例詳解

    xterm.js在web端實(shí)現(xiàn)Terminal示例詳解

    這篇文章主要為大家介紹了xterm.js在web端實(shí)現(xiàn)Terminal示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • TypeScript防抖節(jié)流函數(shù)示例詳解

    TypeScript防抖節(jié)流函數(shù)示例詳解

    這篇文章主要為大家介紹了TypeScript防抖節(jié)流函數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • TypeScript保姆級(jí)基礎(chǔ)教程

    TypeScript保姆級(jí)基礎(chǔ)教程

    這篇文章主要為大家介紹了TypeScript保姆級(jí)基礎(chǔ)教程示例詳解,主要為大家介紹了typescript的類(lèi)型,函數(shù),對(duì)象,接口等基礎(chǔ)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-07-07
  • typescript難學(xué)嗎?前端有必要學(xué)?該怎么學(xué)typescript

    typescript難學(xué)嗎?前端有必要學(xué)?該怎么學(xué)typescript

    TypeScript代碼與?JavaScript?代碼有非常高的兼容性,無(wú)門(mén)檻,你把?JS?代碼改為?TS?就可以運(yùn)行。TypeScript?應(yīng)該不會(huì)脫離?JavaScript?成為獨(dú)立的語(yǔ)言。學(xué)習(xí)?TypeScript?應(yīng)該主要指的是學(xué)習(xí)它的類(lèi)型系統(tǒng)。
    2022-12-12
  • js 獲取今天以及過(guò)去日期

    js 獲取今天以及過(guò)去日期

    這篇文章主要介紹了js獲得當(dāng)前系統(tǒng)日期時(shí)間以及過(guò)去系統(tǒng)日期時(shí)間的方法,涉及javascript操作日期時(shí)間的相關(guān)技巧,示例代碼如下,需要的朋友可以參考下
    2017-04-04
  • TypeScript類(lèi)型級(jí)別和值級(jí)別示例詳解

    TypeScript類(lèi)型級(jí)別和值級(jí)別示例詳解

    這篇文章主要為大家介紹了TypeScript類(lèi)型級(jí)別和值級(jí)別示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • TypeScript數(shù)據(jù)結(jié)構(gòu)鏈表結(jié)構(gòu)?LinkedList教程及面試

    TypeScript數(shù)據(jù)結(jié)構(gòu)鏈表結(jié)構(gòu)?LinkedList教程及面試

    這篇文章主要為大家介紹了TypeScript數(shù)據(jù)結(jié)構(gòu)鏈表結(jié)構(gòu)?LinkedList教程及面試,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • TypeScript數(shù)據(jù)結(jié)構(gòu)之隊(duì)列結(jié)構(gòu)Queue教程示例

    TypeScript數(shù)據(jù)結(jié)構(gòu)之隊(duì)列結(jié)構(gòu)Queue教程示例

    這篇文章主要為大家介紹了TypeScript數(shù)據(jù)結(jié)構(gòu)之隊(duì)列結(jié)構(gòu)Queue教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • typescript快速上手的基礎(chǔ)知識(shí)篇

    typescript快速上手的基礎(chǔ)知識(shí)篇

    靜態(tài)類(lèi)型的typescript與傳統(tǒng)動(dòng)態(tài)弱類(lèi)型語(yǔ)言javascript不同,在執(zhí)行前會(huì)先編譯成javascript,因?yàn)樗鼜?qiáng)大的type類(lèi)型系統(tǒng)加持,能讓我們?cè)诰帉?xiě)代碼時(shí)增加更多嚴(yán)謹(jǐn)?shù)南拗啤W⒁?,它并不是一門(mén)全新的語(yǔ)言,所以并沒(méi)有增加額外的學(xué)習(xí)成本
    2022-12-12
  • Nest框架中集成使用Swagger示例說(shuō)明

    Nest框架中集成使用Swagger示例說(shuō)明

    這篇文章主要為大家介紹了Nest框架中集成使用Swagger的示例說(shuō)明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08

最新評(píng)論