广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >TypeScript数据类型中模板字面量的示例分析
  • 482
分享到

TypeScript数据类型中模板字面量的示例分析

2024-04-02 19:04:59 482人浏览 薄情痞子
摘要

这篇文章主要为大家展示了“typescript数据类型中模板字面量的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“TypeScript数据类型中模板字面

这篇文章主要为大家展示了“typescript数据类型中模板字面量的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“TypeScript数据类型中模板字面量的示例分析”这篇文章吧。

模板字面量类型(Template Literal Types)

模板字面量类型以字符串字面量类型为基础,可以通过联合类型扩展成多个字符串。

它们跟 javascript 的模板字符串是相同的语法,但是只能用在类型操作中。当使用模板字面量类型时,它会替换模板中的变量,返回一个新的字符串字面量:

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

当模板中的变量是一个联合类型时,每一个可能的字符串字面量都会被表示:

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"

如果模板字面量里的多个变量都是联合类型,结果会交叉相乘,比如下面的例子就有 2 2 3 一共 12 种结果:

type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;
type Lang = "en" | "ja" | "pt";
 
type LocaleMessageIDs = `${Lang}_${AllLocaleIDs}`;
// type LocaleMessageIDs = "en_welcome_email_id" | "en_email_heading_id" | "en_footer_title_id" | "en_footer_sendoff_id" | "ja_welcome_email_id" | "ja_email_heading_id" | "ja_footer_title_id" | "ja_footer_sendoff_id" | "pt_welcome_email_id" | "pt_email_heading_id" | "pt_footer_title_id" | "pt_footer_sendoff_id"

如果真的是非常长的字符串联合类型,推荐提前生成,这种还是适用于短一些的情况。

类型中的字符串联合类型(String UNIOns in Types)

模板字面量最有用的地方在于你可以基于一个类型内部的信息,定义一个新的字符串,让我们举个例子:

有这样一个函数 makeWatchedObject, 它会给传入的对象添加了一个 on  方法。在 JavaScript 中,它的调用看起来是这样:makeWatchedObject(baseObject),我们假设这个传入对象为:

const passedObject = {
  firstName: "Saoirse",
  lastName: "Ronan",
  age: 26,
};

这个 on 方法会被添加到这个传入对象上,该方法接受两个参数,eventNamestring 类型) 和 callBackfunction 类型):

// 伪代码
const result = makeWatchedObject(baseObject);
result.on(eventName, callBack);

我们希望 eventName 是这种形式:attributeInThePassedObject + "Changed" ,举个例子,passedObject 有一个属性 firstName,对应产生的 eventNamefirstNameChanged,同理,lastName 对应的是 lastNameChangedage 对应的是 ageChanged

当这个 callBack 函数被调用的时候:

  • 应该被传入与 attributeInThePassedObject 相同类型的值。比如 passedObject 中, firstName 的值的类型为 string , 对应 firstNameChanged 事件的回调函数,则接受传入一个 string  类型的值。age 的值的类型为 number,对应 ageChanged 事件的回调函数,则接受传入一个 number 类型的值。

  • 返回值类型为 void 类型。

on() 方法的签名最一开始是这样的:on(eventName: string, callBack: (newValue: any) => void)。 使用这样的签名,我们是不能实现上面所说的这些约束的,这个时候就可以使用模板字面量:

const person = makeWatchedObject({
  firstName: "Saoirse",
  lastName: "Ronan",
  age: 26,
});
 
// makeWatchedObject has added `on` to the anonymous Object
person.on("firstNameChanged", (newValue) => {
  console.log(`firstName was changed to ${newValue}!`);
});

注意这个例子里,on 方法添加的事件名为 "firstNameChanged", 而不仅仅是 "firstName",而回调函数传入的值 newValue ,我们希望约束为 string 类型。我们先实现第一点。

在这个例子里,我们希望传入的事件名的类型,是对象属性名的联合,只是每个联合成员都还在最后拼接一个 Changed 字符,在 JavaScript 中,我们可以做这样一个计算:

Object.keys(passedObject).map(x => ${x}Changed)

模板字面量提供了一个相似的字符串操作:

type PropEventSource<Type> = {
    on(eventName: `${string & keyof Type}Changed`, callback: (newValue: any) => void): void;
};
 
/// Create a "watched object" with an 'on' method
/// so that you can watch for changes to properties.

declare function makeWatchedObject<Type>(obj: Type): Type & PropEventSource<Type>;

注意,我们在这里例子中,模板字面量里我们写的是 string & keyof Type,我们可不可以只写成 keyof Type 呢?如果我们这样写,会报错:

type PropEventSource<Type> = {
    on(eventName: `${keyof Type}Changed`, callback: (newValue: any) => void): void;
};

// Type 'keyof Type' is not assignable to type 'string | number | bigint | boolean | null | undefined'.
// Type 'string | number | symbol' is not assignable to type 'string | number | bigint | boolean | null | undefined'.
// ...

从报错信息中,我们也可以看出报错原因,在 《TypeScript 系列之 Keyof 操作符》里,我们知道 keyof 操作符会返回 string | number | symbol 类型,但是模板字面量的变量要求的类型却是 string | number | bigint | boolean | null | undefined,比较一下,多了一个 symbol 类型,所以其实我们也可以这样写:

type PropEventSource<Type> = {
    on(eventName: `${Exclude<keyof Type, symbol>}Changed`, callback: (newValue: any) => void): void;
};

再或者这样写:

type PropEventSource<Type> = {
     on(eventName: `${Extract<keyof Type, string>}Changed`, callback: (newValue: any) => void): void;
};

使用这种方式,在我们使用错误的事件名时,TypeScript 会给出报错:

const person = makeWatchedObject({
  firstName: "Saoirse",
  lastName: "Ronan",
  age: 26
});
 
person.on("firstNameChanged", () => {});
 
// Prevent easy human error (using the key instead of the event name)
person.on("firstName", () => {});
// Argument of type '"firstName"' is not assignable to parameter of type '"firstNameChanged" | "lastNameChanged" | "ageChanged"'.
 
// It's typo-resistant
person.on("frstNameChanged", () => {});
// Argument of type '"frstNameChanged"' is not assignable to parameter of type '"firstNameChanged" | "lastNameChanged" | "ageChanged"'.

模板字面量的推断(Inference with Template Literals)

现在我们来实现第二点,回调函数传入的值的类型与对应的属性值的类型相同。我们现在只是简单的对 callBack 的参数使用 any 类型。实现这个约束的关键在于借助泛型函数:

  • 捕获泛型函数第一个参数的字面量,生成一个字面量类型

  • 该字面量类型可以被对象属性构成的联合约束

  • 对象属性的类型可以通过索引访问获取

  • 应用此类型,确保回调函数的参数类型与对象属性的类型是同一个类型

type PropEventSource<Type> = {
    on<Key extends string & keyof Type>
        (eventName: `${Key}Changed`, callback: (newValue: Type[Key]) => void ): void;
};
 
declare function makeWatchedObject<Type>(obj: Type): Type & PropEventSource<Type>;

const person = makeWatchedObject({
  firstName: "Saoirse",
  lastName: "Ronan",
  age: 26
});
 
person.on("firstNameChanged", newName => {                             
                                                          // (parameter) newName: string
    console.log(`new name is ${newName.toUpperCase()}`);
});
 
person.on("ageChanged", newAge => {
                        // (parameter) newAge: number
    if (newAge < 0) {
        console.warn("warning! negative age");
    }
})

这里我们把 on 改成了一个泛型函数。

当一个用户调用的时候传入 "firstNameChanged",TypeScript 会尝试着推断 Key 正确的类型。它会匹配 key"Changed" 前的字符串 ,然后推断出字符串 "firstName" ,然后再获取原始对象的 firstName 属性的类型,在这个例子中,就是 string 类型。

内置字符操作类型(Intrinsic String Manipulation Types)

TypeScript 的一些类型可以用于字符操作,这些类型处于性能的考虑被内置在编译器中,你不能在 .d.ts 文件里找到它们。

Uppercase<StringType>

把每个字符转为大写形式:

type Greeting = "Hello, world"
type ShoutyGreeting = Uppercase<Greeting>        
// type ShoutyGreeting = "HELLO, WORLD"
 
type ASCIICacheKey<Str extends string> = `ID-${Uppercase<Str>}`
type MainID = ASCIICacheKey<"my_app">
// type MainID = "ID-MY_APP"

Lowercase<StringType>

把每个字符转为小写形式:

type Greeting = "Hello, world"
type QuietGreeting = Lowercase<Greeting>       
// type QuietGreeting = "hello, world"
 
type ASCIICacheKey<Str extends string> = `id-${Lowercase<Str>}`
type MainID = ASCIICacheKey<"MY_APP">    
// type MainID = "id-my_app"

Capitalize<StringType>

把字符串的第一个字符转为大写形式:

type LowercaseGreeting = "hello, world";
type Greeting = Capitalize<LowercaseGreeting>;
// type Greeting = "Hello, world"

Uncapitalize<StringType>

把字符串的第一个字符转换为小写形式:

type UppercaseGreeting = "HELLO WORLD";
type UncomfortableGreeting = Uncapitalize<UppercaseGreeting>;           
// type UncomfortableGreeting = "hELLO WORLD"

字符操作类型的技术细节

从 TypeScript 4.1 起,这些内置函数会直接使用 JavaScript 字符串运行时函数,而不是本地化识别 (locale aware)。

function applyStringMapping(symbol: Symbol, str: string) {
    switch (intrinsicTypeKinds.get(symbol.escapedName as string)) {
        case IntrinsicTypeKind.Uppercase: return str.toUpperCase();
        case IntrinsicTypeKind.Lowercase: return str.toLowerCase();
        case IntrinsicTypeKind.Capitalize: return str.charAt(0).toUpperCase() + str.slice(1);
        case IntrinsicTypeKind.Uncapitalize: return str.charAt(0).toLowerCase() + str.slice(1);
    }
    return str;
}

以上是“TypeScript数据类型中模板字面量的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网node.js频道!

--结束END--

本文标题: TypeScript数据类型中模板字面量的示例分析

本文链接: https://www.lsjlt.com/news/87842.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • TypeScript数据类型中模板字面量的示例分析
    这篇文章主要为大家展示了“TypeScript数据类型中模板字面量的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“TypeScript数据类型中模板字面...
    99+
    2022-10-19
  • Typescript中数据类型的示例分析
    这篇文章将为大家详细讲解有关Typescript中数据类型的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。是什么typescript和javascript几乎一样,拥有相同的数据类型,另外在jav...
    99+
    2023-06-29
  • TypeScript中基本数据类型的示例分析
    这篇文章主要为大家展示了“TypeScript中基本数据类型的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“TypeScript中基本数据类型的示例分析...
    99+
    2022-10-19
  • TypeScript 4.1中的模板字面类型是什么
    这篇文章主要介绍“TypeScript 4.1中的模板字面类型是什么”,在日常操作中,相信很多人在TypeScript 4.1中的模板字面类型是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”TypeScr...
    99+
    2023-06-15
  • js数据类型之数字类型的示例分析
    这篇文章主要介绍了js数据类型之数字类型的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。我们具体介绍一下js的数据类型其中一种。一、...
    99+
    2022-10-19
  • JavaScript中变量、数据类型的示例分析
    小编给大家分享一下JavaScript中变量、数据类型的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1 如何声明变量变...
    99+
    2022-10-19
  • Pytorch张量数据类型的示例分析
    Pytorch张量数据类型的示例分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1.python 和 pytorch的数据类型区别在PyTorch中无法展示字符串,因此表达字...
    99+
    2023-06-25
  • JavaScript中数据类型的示例分析
    这篇文章主要介绍JavaScript中数据类型的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一,数据类型以下内容基于ES5(ES6引入了一种新的原始数据类型Symbol,表...
    99+
    2022-10-19
  • PHP5.4中语法、常量、变量、数据类型的示例分析
    这篇文章主要介绍了PHP5.4中语法、常量、变量、数据类型的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、php5.4的基本语法...
    99+
    2022-10-19
  • ES6中模板字符串的示例分析
    这篇文章主要为大家展示了“ES6中模板字符串的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“ES6中模板字符串的示例分析”这篇文章吧。模板字符串(tem...
    99+
    2022-10-19
  • redis数据类型的示例分析
    这篇文章主要介绍redis数据类型的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Redis支持5种数据类型,它们描述如下:Strings - 字符串Redis的字符串是字节...
    99+
    2022-10-18
  • javascript数据类型的示例分析
    这篇文章将为大家详细讲解有关javascript数据类型的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1. undefined 和 nullundefined是...
    99+
    2022-10-19
  • Oracle中CLOB大数据字段类型操作的示例分析
    这篇文章主要为大家展示了“Oracle中CLOB大数据字段类型操作的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Oracle中CLOB大数据字段类型操...
    99+
    2022-10-18
  • PHP数据类型之NULL型的示例分析
    这篇文章给大家分享的是有关PHP数据类型之NULL型的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1:什么是NULL?对于MULL这个单词来说,他代表着空,并非是错误(false)以及0,也不是我们常用...
    99+
    2023-06-15
  • python列表中数据类型的示例分析
    这篇文章给大家分享的是有关python列表中数据类型的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。python的五大特点是什么python的五大特点:1.简单易学,开发程序时,专注的是解决问题,而不是搞...
    99+
    2023-06-14
  • C语言中数据类型的示例分析
    这篇文章将为大家详细讲解有关C语言中数据类型的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。(壹) 数据类型介绍前面我们已经学习了基本的内置类型,以及他们所占存储空间的大小。:类型的意义...
    99+
    2023-06-29
  • Java数据类型转换的示例分析
    这篇文章将为大家详细讲解有关 Java数据类型转换的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 Java数据类型转换1.Java的简单类型及其封装器类⑴Java简单类型与封装类我们知...
    99+
    2023-06-17
  • JavaScript数据类型转换的示例分析
    这篇文章主要介绍JavaScript数据类型转换的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!JS数据类型在 JavaScript 语言中数据类型分为2大类:基本数据类型和复杂数据类型基本数据类型有:num...
    99+
    2023-06-15
  • Python中的变量和数据类型实例分析
    本篇内容介绍了“Python中的变量和数据类型实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!python是一门弱数据类型的语言,变量...
    99+
    2023-06-29
  • PHP中标量类型、复合类型和特殊类型的示例分析
    这篇文章主要介绍了PHP中标量类型、复合类型和特殊类型的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在PHP中,支持8种原始数据类型,其中包括四种标量类型、两种复合...
    99+
    2023-06-20
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作