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

TypeScript類型操作之字符串處理功能詳解

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

引言

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

模板字符串

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

let str = `user name is : ${name}`; // 插值表達式
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中的應用不是本文我們的重點,如果大家想深入了解一下可以先看看MDN然后再翻翻ECMAScript的規(guī)范基本上就很深入了。主要是介紹在 TypeScript 中,支持了哪些特性,提供了什么能力。

TS 中模板字符串的相關特性

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

構造新的類型

普通插值表達式,構造一個復合型的字符串類型。

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

在插值位置使用聯(lián)合類型時,構造出一個新的字符串聯(lián)合類型。

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"
*/
// 換個位置構造
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 會動態(tài)遍歷插值中的聯(lián)合類型,然后構造出所有情況下組合出來的并集聯(lián)合類型。這在我們項目中組合出新的類型挺實用。

使用模板字符串進行推理

基于對象類型內(nèi)部屬性名構造字符串類型,然后根據(jù)對象類型中對應的屬性值類型進行推導新的類型。功能會很強大。我們以一個案例進行解釋:題目是對一個對象進行代理,代理后需要監(jiān)聽到這個對象的變化事件,現(xiàn)在需要定義一套類型來實現(xià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)在我們需要使用類型來對 調用 on 上注冊的事件名稱做檢查:要求on監(jiān)聽的屬性名稱必須滿足(屬性名+ 'Changed' ) 格式,監(jiān)聽函數(shù)返回值類型和原對象一致【監(jiān)聽name,返回值類型是 string、監(jiān)聽age返回值類型是number】。我們分三步實現(xiàn)一下這個類型的定義。

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

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

第二步:定義一個類型工具,負責提取類型上的屬性作為模板字符串的插值。大家不清楚 extends 、 keyof 用法的請看這篇文章 《TypeScript 玩轉類型操作之基礎篇》,里面詳細介紹了其使用場景以及方式,包含與 typeof、infer 等關鍵詞的配合使用以及Omit等高級類型的源碼解析。

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ù)的修飾, 并提取目標類型上的值類型作為callback參數(shù)的類型。

// 定義一個工具類型,特殊處理定義一個 on 函數(shù)的類型,主要是修飾 on 的參數(shù)類型
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 在編譯過程中,編譯器會將代碼解析成 AST (抽象語法樹)。對于模板字符串編譯器會識別出模板字符串的靜態(tài)部分(普通的字符文本)和動態(tài)部分(插值表達式)解析的結果仍然是AST結構,完成解析以后TypeScript 會進行類型推導。類型推導時編譯器會分析每個插值表達式的類型,根據(jù)類型不同進行轉換推導出整個模板字符串的類型。這里會有類似于 JavaScript 類型轉換的場景非字符如何 toPrimitive 。

TS代碼:

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

解析成類似AST語法樹:

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

解析模板字符串的結構,然后根據(jù)插值表達式的類型推導出整個模板字符串的類型。

字符串操作工具類型【有的說是高級類型】

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

我們來分別看看他們的功能:

Uppercase<StringType>

將字符串中的每個字母都轉換成大寫。

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

我們來實現(xiàn)這樣一個簡單的題目:將一個對象上的所有屬性名提取出來,并轉成大寫。

// 限制一下K從T的屬性中提取,并且是string類型
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"
// 如果你想只有一個入口,也可以這樣再封一個自定義的類型工具
type A<T extends { [k: string ]: any }> = PickPropertyToUppercase<T, keyof T>;
type APerType = A<typeof per>
//type APerType = "NAME" | "AGE"

這些基礎能力結合我們上一篇文章中的類型基礎【keyof、 typeof、infer、extends、條件類型~】就是我們玩轉體操的基礎啦~

Lowercase<StringType>

將字符串中所有的字母都變成小寫,和 Uppercase 用法是類似的。

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

Capitalize<StringType>、Uncapitalize<StringType>

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

比如: aa_bb_cc 轉換成 aaBbCc 。

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

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

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

第二步:在第一步的基礎上將 FirstStr、LastStr 首字母大寫進行組合。

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

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

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 這個方式就很簡單了 直接調用一次 Uncapitalize 
type LowerCamel<T extends string> = Uncapitalize<UpperCamel<T>>;
type lowerCamelStr = LowerCamel<"aa_bb_cc___dd">
// type lowerCamelStr = "aaBbCcDd"

至此,字符串的類型操作以及模板字符串中的相關技術點就介紹完了。結合《TypeScript 玩轉類型操作之基礎篇》我們體操的能力已經(jīng)具備,下一篇我們搞幾個面試中經(jīng)常被問到的TS體操操作,練練手。歡迎大家評論區(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類型操作之字符串處理功能詳解的詳細內(nèi)容,更多關于TypeScript類型操作字符串處理的資料請關注腳本之家其它相關文章!

相關文章

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

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

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

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

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

    TypeScript保姆級基礎教程

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

    typescript難學嗎?前端有必要學?該怎么學typescript

    TypeScript代碼與?JavaScript?代碼有非常高的兼容性,無門檻,你把?JS?代碼改為?TS?就可以運行。TypeScript?應該不會脫離?JavaScript?成為獨立的語言。學習?TypeScript?應該主要指的是學習它的類型系統(tǒng)。
    2022-12-12
  • js 獲取今天以及過去日期

    js 獲取今天以及過去日期

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

    TypeScript類型級別和值級別示例詳解

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

    TypeScript數(shù)據(jù)結構鏈表結構?LinkedList教程及面試

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

    TypeScript數(shù)據(jù)結構之隊列結構Queue教程示例

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

    typescript快速上手的基礎知識篇

    靜態(tài)類型的typescript與傳統(tǒng)動態(tài)弱類型語言javascript不同,在執(zhí)行前會先編譯成javascript,因為它強大的type類型系統(tǒng)加持,能讓我們在編寫代碼時增加更多嚴謹?shù)南拗?。注意,它并不是一門全新的語言,所以并沒有增加額外的學習成本
    2022-12-12
  • Nest框架中集成使用Swagger示例說明

    Nest框架中集成使用Swagger示例說明

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

最新評論