Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of template literals in TypeScript data Type

2025-01-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly shows you the "sample analysis of the literals of templates in the TypeScript data type", which is easy to understand and well-organized. I hope it can help you solve your doubts. Let me lead you to study and learn the "sample analysis of the literals of templates in the TypeScript data type".

Template literal type (Template Literal Types)

The template literal type is based on the string literal type and can be extended to multiple strings by associating types.

They have the same syntax as JavaScript's template strings, but can only be used in type operations. When the template literal type is used, it replaces the variable in the template and returns a new string literal:

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

When the variable in the template is a federated type, every possible literal amount of the string is represented:

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"

If multiple variables in the literal quantity of the template are joint types, the results will be cross-multiplied. For example, in the following example, there are 22, 3 and 12 results:

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"

If it is really a very long string concatenation type, it is recommended to generate it in advance, which is still suitable for shorter cases.

String association type in type (String Unions in Types)

The most useful thing about template literals is that you can define a new string based on information within a type. Let's give an example:

There is a function makeWatchedObject that adds an on method to the incoming object. In JavaScript, its call looks like this: makeWatchedObject (baseObject), let's assume that the incoming object is:

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

The on method is added to the incoming object, which takes two parameters, eventName (type string) and callBack (type function):

/ / pseudo code const result = makeWatchedObject (baseObject); result.on (eventName, callBack)

We want eventName to be in this form: attributeInThePassedObject + "Changed". For example, passedObject has an attribute firstName, and the resulting eventName is firstNameChanged. Similarly, lastName corresponds to lastNameChanged,age and corresponds to ageChanged.

When the callBack function is called:

Should be passed a value of the same type as attributeInThePassedObject. For example, in passedObject, the value of firstName is of type string, and the callback function corresponding to the firstNameChanged event accepts a value of type string. The value of age is of type number, and the callback function of the ageChanged event accepts a value of type number.

The return value is of type void.

The signature of the on () method starts with this: on (eventName: string, callBack: (newValue: any) = > void). With such a signature, we cannot implement the above constraints, so we can use the template literal at this time:

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

Note that in this example, the event added by the on method is named "firstNameChanged", not just "firstName", while the value passed in by the callback function, newValue, we want to be constrained to the string type. Let's achieve the first point first.

In this example, we want the type of event name passed in to be a union of object attribute names, but each union member is still concatenating a Changed character at the end. In JavaScript, we can do this calculation:

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

Template literals provide a similar string operation:

Type PropEventSource = {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 (obj: Type): Type & PropEventSource

Note that in our example here, we write string & keyof Type literally in the template, can we just write keyof Type? If we write like this, we will report an error:

Type PropEventSource = {on (eventName: `${keyof Type} Changed`, callback: (newValue: any) = > void): void;}; / / Type' keyof Type' is not assignable to type 'string | number | bigint | boolean | null | number | symbol' is not assignable to type' string | number | bigint | boolean | null | undefined'.//.

From the error message, we can also see the reason for the error. In the "Keyof operator of TypeScript series", we know that the keyof operator will return string | number | symbol, but the literal variable of the template requires a type of string | number | bigint | boolean | null | undefined. By comparison, there is an additional symbol type, so we can also write this:

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

Or write something like this:

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

In this way, TypeScript will report an error when we use the wrong event name:

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-resistantperson.on ("frstNameChanged", () = > {}); / / Argument of type'"frstNameChanged"'is not assignable to parameter of type'"firstNameChanged" | "lastNameChanged" | "ageChanged"'. Inference of template literals (Inference with Template Literals)

Now let's implement the second point, that the value passed in by the callback function is of the same type as the corresponding property value. We are now simply using the any type for the parameters of callBack. The key to this constraint is with the help of generic functions:

Capture the literal quantity of the first argument of a generic function to generate a literal type

The literal type can be jointly constrained by object attributes.

The type of object property can be obtained through index access

Apply this type to ensure that the parameter type of the callback function is the same type as the type of the object property

Type PropEventSource = {on (eventName: `${Key} Changed`, callback: (newValue: Type [Key]) = > void): void;}; declare function makeWatchedObject (obj: Type): Type & PropEventSource;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 ");}})

Here we change on to a generic function.

When a user calls "firstNameChanged", TypeScript tries to infer the correct type of Key. It matches the string before key and "Changed", deduces the string "firstName", and then gets the type of the firstName property of the original object, in this case, the string type.

Built-in character operation type (Intrinsic String Manipulation Types)

Some types of TypeScript can be used for character manipulation, these types are built into the compiler for performance reasons, and you can't find them in the .d.ts file.

Uppercase

Convert each character to uppercase:

Type Greeting = "Hello, world" type ShoutyGreeting = Uppercase / / type ShoutyGreeting = "HELLO, WORLD" type ASCIICacheKey = `ID-$ {Uppercase} `type MainID = ASCIICacheKey// type MainID = "ID-MY_APP" Lowercase

Convert each character to lowercase:

Type Greeting = "Hello, world" type QuietGreeting = Lowercase / / type QuietGreeting = "hello, world" type ASCIICacheKey = `id-$ {Lowercase} `type MainID = ASCIICacheKey / / type MainID = "id-my_app" Capitalize

Convert the first character of a string to uppercase:

Type LowercaseGreeting = "hello, world"; type Greeting = Capitalize;// type Greeting = "Hello, world" Uncapitalize

Converts the first character of a string to lowercase:

Type UppercaseGreeting = "HELLO WORLD"; type UncomfortableGreeting = Uncapitalize; / / type UncomfortableGreeting = "hELLO WORLD" character operation type technical details

Starting with TypeScript 4. 1, these built-in functions directly use JavaScript string runtime functions instead of localized identification (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 } the above is all the content of the article "sample Analysis of template literals in TypeScript data types". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report