typescript类属性取值耗时(typescript 特殊符号)

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

本文主要向您展示“TypeScript数据类型中模板文字的示例分析”,简单易懂,组织清晰,希望能帮您解决疑惑。让边肖带领您学习和学习文章“TypeScript数据类型中模板文字的示例分析”。

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

模板文字类型基于字符串文字类型,可以通过union类型扩展成多个字符串。

它们具有与JavaScript模板字符串相同的语法,但只能在类型操作中使用。当使用模板文字类型时,它将替换模板中的变量并返回一个新的字符串文字:

typeWorld=' world

type hello=` hello $ { World } `;

//类型问候语='helloworld '当模板中的变量是联合类型时,每个可能的文字字符串都将被表示为:

typeemailillcaleids=' welcome _ email ' | ' email _ heading ';

typeFooterLocaleIDs=' footer _ title ' | ' footer _ send off ';

typellocaleids=` $ { emaillcaleids | FooterLocaleIDs } _ id `;

//typealloclides=' Welcome _ email _ ID ' | ' email _ heading _ ID ' | ' footer _ title _ ID ' | ' footer _ sendoff _ ID '如果模板文字中的多个变量为联合类型,则结果会交叉相乘。例如,以下示例中有2 2 3个结果:

typellocaleids=` $ { emaillcaleids | FooterLocaleIDs } _ id `;

typeLang=' en ' | ' ja ' | ' pt

typellocalemessageds=` $ { Lang } _ $ { AllLocaleIDs } `;

//typelocalemessageds=' en _ welcome _ email _ ID ' | ' en _ email _ heading _ ID ' | ' en _ footer _ title _ ID ' | ' en _ footer _ sendoff _ ID ' | ' Ja _ welcome _ email _ ID ' | ' Ja _ footer _ title _ ID ' | ' Ja _ footer _ sendoff _ ID ' | ' PT _ welcome _ email _ ID ' | ' PT _ email _ heading _ ID ' | ' PT _ footer _ title _ ID '

00-1010模板文字最有用的地方是,您可以基于类型内部的信息定义一个新字符串。让我们举个例子:

有一个函数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数据类型中模板字面量的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/152464.html

(0)

相关推荐

  • JQuery如何删除UL最后一个li

    技术JQuery如何删除UL最后一个li本篇内容主要讲解“JQuery如何删除UL最后一个li”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JQuery如何删除UL最后一个l

    攻略 2021年11月15日
  • 如何租用香港服务器更便宜

    技术如何租用香港服务器更便宜由于每个网站都会有独特的硬件配置需求需求。而不同类型的服务器需要的硬件配置的价格也是不一样的,出于这个原因,对于不同类型的网站所有者,都没有所谓最便宜的的香港服务器。作为网站多有者在租用服务器

    礼包 2021年10月19日
  • Dubbo重要概念分析

    技术Dubbo重要概念分析这期内容当中小编将会给大家带来有关Dubbo重要概念分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1.proxyFactory:就是为了获取一个接口的代理

    攻略 2021年11月12日
  • 脂肪代谢过程,人体内物质代谢转化过程

    技术脂肪代谢过程,人体内物质代谢转化过程(1)糖类代谢与蛋白质代谢的关系 ①糖类代谢的中间产物可以转变成非必需氨基酸脂肪代谢过程。
    糖类在分解过程中产生的一些中间产物如丙酮酸,可以通过氨基转换作用产生相应的非必需氨基酸,

    生活 2021年10月24日
  • 至于颠覆,物理学中有什么颠覆世界观的理论

    技术至于颠覆,物理学中有什么颠覆世界观的理论量子力学的诡异现象量子力学也是自然科学史上被实验证明最精确的一个理论,但是量子的观念,没有人能够理解至于颠覆。我说的没有人能够理解,绝不是指像我们这个层次的人,而是说连量子力学

    生活 2021年10月20日
  • 什么是InnoDB存储引擎

    技术什么是InnoDB存储引擎这篇文章主要介绍“什么是InnoDB存储引擎”,在日常操作中,相信很多人在什么是InnoDB存储引擎问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”什么是Inn

    攻略 2021年10月28日