前言
在现代 JavaScript 开发中,TypeScript 作为一种强类型的超集,越来越受到开发者的青睐。它不仅提升了代码的可读性和可维护性,还为复杂应用的构建提供了强大的类型系统。本文将探讨 TypeScript 中的一些核心特性,包括泛型、约束、枚举以及字符操作。我们将通过具体的代码示例,深入理解如何定义和使用泛型函数、类和接口,以及如何利用 keyof
约束类型,确保代码的类型安全。此外,我们还将讨论枚举的定义与使用,区分常量枚举和外部枚举的特点。最后,我们将简要介绍可选链操作符 ?.
和空值合并操作符 ??
,这些工具将在处理潜在空值时为我们提供便利。无论您是 TypeScript 的新手还是希望深化理解的开发者,本文都将为您提供实用的知识和技巧,帮助您更高效地进行 TypeScript 开发。
简单使用
<script setup lang="ts"> // function person<T>(a:T,b:T):Array<T>{ // return [a,b] // // } // let a1 = person(1,2); // let a2 = person(false,true); // // 类型别名 // type A<T>=string | null | T // let a:A<boolean>=true // A<any> // interface Data<T>{ // msg:T // } // let data:Data<number>={ // msg:1 // } // function add<T,K>(a:T,b:K):Array<T | K>{ // return [a,b] // } // let a = add(1,false); // 简单 整理 const axios = { get<T>(url:string){ return new Promise((resolve,reject)=>{ let xhr:XMLHttpRequest = new XMLHttpRequest() xhr.open('GET',url) xhr.onreadystatechange=()=>{ if(xhr.readyState==4&&xhr.status==200){ resolve(JSON.parse(xhr.responseText)) } } xhr.send(null) }) } } interface Data{ msg:string, code:number } axios.get<Data>('./data.json').then(res=>{ console.log(res) }) </script>
约束
keyof
<script lang="ts"> interface Len{ length:number } function fn<T extends Len>(a:T){ a.length } fn("111") fn([12,321]) let obj={ name:"youren", sex:"boy", } type key = keyof typeof obj function ob<T extends Object,K extends keyof T>(obj:T,key:K){ return obj[key] } ob(obj,'name') interface Data{ name?:string, age?:number, sex?:number } type Options<T extends Object>={ [key in keyof T]?:T[key] } type B = Options<Data> </script>
理解
我们可以把泛型比喻为一个类型占位符,它告诉编译器:“嘿,这里有一个类型参数,我现在不确定具体是什么类型,但稍后会告诉你。
使用泛型变量 T 现在假设我们想操作 T 类型的数组而不直接是 T 。由于我们操作的是数组,所以 .length 属性是应该存在的。 我们可以像创建其它数组一样创建这个数组: function loggingIdentity<T>(arg: T[]): T[] { console.log(arg.length); // Array has a .length, so no more error return arg; }
// 示例1: 创建一个泛型函数 function identity<T>(arg: T): T { return arg; } // 示例2: 使用泛型函数 let output = identity<string>("Hello"); console.log(output); // 输出: Hello // 示例3: 使用类型推断,自动推断泛型类型 let output2 = identity("Hello"); console.log(output2); // 输出: Hello
function reverse<T>(array: T[]): T[] { return array.reverse(); }
class Box<T> { private value: T; constructor(value: T) { this.value = value; } getValue(): T { return this.value; } } let box1 = new Box<number>(42); console.log(box1.getValue()); // 输出:42 let box2 = new Box<string>("Hello"); console.log(box2.getValue()); // 输出:Hello
写一个转换的
用在写函数 传参数 较多
interface Transformer<T, U> { transform(input: T): U; } class StringToNumberTransformer implements Transformer<string, number> { transform(input: string): number { return parseFloat(input); } } let transformer = new StringToNumberTransformer(); let result = transformer.transform("3.14"); console.log(result); // 输出:3.14
interface people { name: string; age: number; } extend people 约束泛型类 在 people 接口范围内 此时是 泛型变量占位符,在实例化 class 类是传递类型 class Popele<T extends people> { data: T; constructor(data: T) { this.data = data; } hi() { return `${this.data.name},,${this.data.age}`; } } let zhagnsan = new Popele<people>({ name: "张三", age: 18 });
枚举
enum Color{ red, blue, yellow, green="green" } console.log(Color.red, Color.blue, Color.yellow) 可设置red =1 之后会自动 增长 也可以自定义
<script setup lang="ts"> const enum Directions { Up, Down, Left, Right } let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right] // var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */]; console.log(directions) </script>
外部枚举和非外部枚举之间有一个重要的区别,在正常的枚举里,没有初始化方法的成员被当成常量成员。 对于非常量的外部枚举而言,没有初始化方法时被当做需要经过计算的。
declare enum Enum { A = 1, B, C = 2 }
字符
!.
非空断言
首先需要里面有
??
?? 空值合并
不存在就在后面加默认值
let a = undefined console.log(a??'hello')
Plain Text let A={ name:'yoruen', age:10, C:{ sex:1 }, phone:'123' } // 这个 属性就不存在 所以 ? 和! 都没用 ts 中 // 因为ts 中 类型 都 很明确 所以 ? 和 ! 不能用了 const M = A.phone console.log(M)