Top Advanced typescript concepts that Every Developer Should Know

typescript 是一种现代编程语言,由于其附加的类型安全性,通常比 javascript 更受青睐。在本文中,我将分享 10 个最重要的 typescript 概念,这将有助于提高您的 typescript 编程技能。准备好了吗?开始吧。

Top Advanced typescript concepts that Every Developer Should Know

1.泛型:使用泛型我们可以创建可重用的类型,这将有助于处理今天和明天的数据。
泛型示例:
我们可能想要 typescript 中的一个函数将参数作为某种类型,并且我们可能想要返回相同的类型。

function func(args:t):t{    return args;}

2.具有类型约束的泛型:现在让我们通过定义它只接受字符串和整数来限制类型 t:

function func(value: t): t {    return value;}const stringvalue = func("hello"); // works, t is stringconst numbervalue = func(42);      // works, t is number// const booleanvalue = func(true); // error: type 'boolean' is not assignable to type 'string | number'

3.通用接口:
当您想要为使用各种类型的对象、类或函数定义契约(形状)时,接口泛型非常有用。它们允许您定义一个蓝图,该蓝图可以适应不同的数据类型,同时保持结构一致。

// generic interface with type parameters t and uinterface repository {    items: t[];           // array of items of type t    add(item: t): void;   // function to add an item of type t    getbyid(id: u): t | undefined; // function to get an item by id of type u}// implementing the repository interface for a user entityinterface user {    id: number;    name: string;}class userrepository implements repository {    items: user[] = [];    add(item: user): void {        this.items.push(item);    }     getbyid(idorname: number | string): user | undefined {        if (typeof idorname === 'string') {            // search by name if idorname is a string            console.log('searching by name:', idorname);            return this.items.find(user => user.name === idorname);        } else if (typeof idorname === 'number') {            // search by id if idorname is a number            console.log('searching by id:', idorname);            return this.items.find(user => user.id === idorname);        }        return undefined; // return undefined if no match found    }}// usageconst userrepo = new userrepository();userrepo.add({ id: 1, name: "alice" });userrepo.add({ id: 2, name: "bob" });const user1 = userrepo.getbyid(1);const user2 = userrepo.getbyid("bob");console.log(user1); // output: { id: 1, name: "alice" }console.log(user2); // output: { id: 2, name: "bob" }

4.泛型类::当您希望类中的所有属性都遵循泛型参数指定的类型时,请使用此选项。这允许灵活性,同时确保类的每个属性都与传递给类的类型匹配。

interface user {    id: number;    name: string;    age: number;}class userdetails {    id: t['id'];    name: t['name'];    age: t['age'];    constructor(user: t) {        this.id = user.id;        this.name = user.name;        this.age = user.age;    }    // method to get user details    getuserdetails(): string {        return `user: ${this.name}, id: ${this.id}, age: ${this.age}`;    }    // method to update user name    updatename(newname: string): void {        this.name = newname;    }    // method to update user age    updateage(newage: number): void {        this.age = newage;    }}// using the userdetails class with a user typeconst user: user = { id: 1, name: "alice", age: 30 };const userdetails = new userdetails(user);console.log(userdetails.getuserdetails());  // output: "user: alice, id: 1, age: 30"// updating user detailsuserdetails.updatename("bob");userdetails.updateage(35);console.log(userdetails.getuserdetails());  // output: "user: bob, id: 1, age: 35"console.log(new userdetails("30"));  // error: "this will throw error" 

5.将类型参数约束为传递的类型:有时,我们希望参数类型依赖于其他一些传递的参数。听起来很混乱,让我们看下面的示例。

function getproperty(obj: type, key: keyof type) {  return obj[key];}let x = { a: 1, b: 2, c: 3 };getproperty(x, "a");  // validgetproperty(x, "d");  // error: argument of type '"d"' is not assignable to parameter of type '"a" | "b" | "c"'.

6.条件类型:通常,我们希望我们的类型是一种类型或另一种类型。在这种情况下,我们使用条件类型。
一个简单的例子是:

function func(param:number|boolean){return param;}console.log(func(2)) //output: 2 will be printedconsole.log(func("true")) //error: boolean cannot be passed as argument

有点复杂的例子:

type hasproperty = k extends "age" ? "has age" : "has name";interface user {  name: string;  age: number;}let test1: hasproperty;  // "has age"let test2: hasproperty; // "has name"let test3: hasproperty; // error: type '"email"' is not assignable to parameter of type '"age" | "name"'.

6.交集类型:当我们想要将多种类型合并为一个类型时,这些类型非常有用,允许特定类型继承各种其他类型的属性和行为。
让我们看一个有趣的例子:

// defining the types for each area of well-beinginterface mentalwellness {  mindfulnesspractice: boolean;  stresslevel: number; // scale of 1 to 10}interface physicalwellness {  exercisefrequency: string; // e.g., "daily", "weekly"  sleepduration: number; // in hours}interface productivity {  taskscompleted: number;  focuslevel: number; // scale of 1 to 10}// combining all three areas into a single type using intersection typestype healthybody = mentalwellness & physicalwellness & productivity;// example of a person with a balanced healthy bodyconst person: healthybody = {  mindfulnesspractice: true,  stresslevel: 4,  exercisefrequency: "daily",  sleepduration: 7,  taskscompleted: 15,  focuslevel: 8};// displaying the informationconsole.log(person);

7.infer 关键字:当我们想要有条件地确定特定类型时,infer 关键字很有用,并且当条件满足时,它允许我们从该类型中提取子类型。
这是一般语法:

type conditionaltype = t extends sometype ? inferredtype : othertype;

示例:

type returntypeofpromise = t extends promise ? u : number;type result = returntypeofpromise<promise>;  // result is 'string'type errorresult = returntypeofpromise;      // errorresult is 'never'const result: result = "hello";console.log(typeof result); // output: 'string'

8.type variance:这个概念讨论了子类型和父类型如何相互关联。
它们有两种类型:
协方差:可以在需要父类型的地方使用子类型。
让我们看一个例子:

class vehicle { }class car extends vehicle { }function getcar(): car {  return new car();}function getvehicle(): vehicle {  return new vehicle();}// covariant assignmentlet car: car = getcar();let vehicle: vehicle = getvehicle(); // this works because car is a subtype of vehicle

在上面的示例中,car 继承了 vehicle 类的属性,因此将其分配给需要超类型的子类型是绝对有效的,因为子类型将具有超类型所具有的所有属性。
逆变:这与协变相反。我们在子类型应该出现的地方使用超类型。

class vehicle {  startengine() {    console.log("vehicle engine starts");  }}class car extends vehicle {  honk() {    console.log("car honks");  }}function processvehicle(vehicle: vehicle) {  vehicle.startengine(); // this works  // vehicle.honk(); // error: 'honk' does not exist on type 'vehicle'}function processcar(car: car) {  car.startengine(); // works because car extends vehicle  car.honk();        // works because 'car' has 'honk'}let car: car = new car();processvehicle(car); // this works because of contravariance (car can be used as vehicle)processcar(car);     // this works as well because car is of type car// contravariance failure if you expect specific subtype behavior in the method

使用逆变时,我们需要小心不要访问特定于子类型的属性或方法,因为这可能会导致错误。

9。反思: 这个概念涉及在运行时确定变量的类型。虽然 typescript 主要关注编译时的类型检查,但我们仍然可以利用 typescript 运算符在运行时检查类型。
typeof 运算符:我们可以利用 typeof 运算符在运行时查找变量的类型

const num = 23;console.log(typeof num); // "number"const flag = true;console.log(typeof flag); // "boolean"

instanceof 运算符:instanceof 运算符可用于检查对象是否是类或特定类型的实例。

class vehicle {  model: string;  constructor(model: string) {    this.model = model;  }}const benz = new vehicle("mercedes-benz");console.log(benz instanceof vehicle); // true

我们可以使用第三方库在运行时确定类型。

10.依赖注入:依赖注入是一种模式,允许您将代码引入组件中,而无需在组件中实际创建或管理它。虽然它看起来像是使用库,但它有所不同,因为您不需要通过 cdn 或 api 安装或导入它。

乍一看,它似乎也类似于使用函数来实现可重用性,因为两者都允许代码重用。然而,如果我们直接在组件中使用函数,可能会导致它们之间的紧密耦合。这意味着函数或其逻辑的任何变化都可能影响它使用的每个地方。

依赖注入通过将依赖项的创建与使用它们的组件解耦来解决这个问题,使代码更易于维护和测试。

没有依赖注入的示例

// health-related service classes without interfacesclass mentalwellness {  getmentalwellnessadvice(): string {    return "take time to meditate and relax your mind.";  }}class physicalwellness {  getphysicalwellnessadvice(): string {    return "make sure to exercise daily for at least 30 minutes.";  }}// healthadvice class directly creating instances of the servicesclass healthadvice {  private mentalwellnessservice: mentalwellness;  private physicalwellnessservice: physicalwellness;  // directly creating instances inside the class constructor  constructor() {    this.mentalwellnessservice = new mentalwellness();    this.physicalwellnessservice = new physicalwellness();  }  // method to get both mental and physical wellness advice  gethealthadvice(): string {    return `${this.mentalwellnessservice.getmentalwellnessadvice()} also, ${this.physicalwellnessservice.getphysicalwellnessadvice()}`;  }}// creating an instance of healthadvice, which itself creates instances of the servicesconst healthadvice = new healthadvice();console.log(healthadvice.gethealthadvice());// output: "take time to meditate and relax your mind. also, make sure to exercise daily for at least 30 minutes."

依赖注入示例

// Health-related service interfaces with "I" prefixinterface IMentalWellnessService {  getMentalWellnessAdvice(): string;}interface IPhysicalWellnessService {  getPhysicalWellnessAdvice(): string;}// Implementations of the servicesclass MentalWellness implements IMentalWellnessService {  getMentalWellnessAdvice(): string {    return "Take time to meditate and relax your mind.";  }}class PhysicalWellness implements IPhysicalWellnessService {  getPhysicalWellnessAdvice(): string {    return "Make sure to exercise daily for at least 30 minutes.";  }}// HealthAdvice class that depends on services via interfacesclass HealthAdvice {  private mentalWellnessService: IMentalWellnessService;  private physicalWellnessService: IPhysicalWellnessService;  // Dependency injection via constructor  constructor(    mentalWellnessService: IMentalWellnessService,    physicalWellnessService: IPhysicalWellnessService  ) {    this.mentalWellnessService = mentalWellnessService;    this.physicalWellnessService = physicalWellnessService;  }  // Method to get both mental and physical wellness advice  getHealthAdvice(): string {    return `${this.mentalWellnessService.getMentalWellnessAdvice()} Also, ${this.physicalWellnessService.getPhysicalWellnessAdvice()}`;  }}// Dependency injectionconst mentalWellness: IMentalWellnessService = new MentalWellness();const physicalWellness: IPhysicalWellnessService = new PhysicalWellness();// Injecting services into the HealthAdvice classconst healthAdvice = new HealthAdvice(mentalWellness, physicalWellness);console.log(healthAdvice.getHealthAdvice());// Output: "Take time to meditate and relax your mind. Also, Make sure to exercise daily for at least 30 minutes."

在紧密耦合的场景中,如果您今天 mentalwellness 类中有一个stresslevel 属性,并决定明天将其更改为其他属性,则需要更新所有使用它的地方。这可能会导致许多重构和维护挑战。

但是,通过依赖注入和接口的使用,你可以避免这个问题。通过构造函数传递依赖项(例如 mentalwellness 服务),具体的实现细节(例如stresslevel 属性)被抽象到接口后面。这意味着只要接口保持不变,对属性或类的更改不需要修改依赖类。这种方法可确保代码松散耦合、更易于维护且更易于测试,因为您可以在运行时注入所需的内容,而无需紧密耦合组件。

以上就是Top Advanced typescript concepts that Every Developer Should Know的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1497682.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
对象属性的点表示法与括号表示法 – 有什么区别?
上一篇 2025年12月19日 19:44:36
如何从会话历史记录中提取特定问题对应的所有回答?
下一篇 2025年12月19日 19:44:46

相关推荐

  • Golang JSON序列化:控制敏感字段暴露的最佳实践

    本教程探讨golang中如何高效控制结构体字段在json序列化时的可见性。当需要将包含敏感信息的结构体数组转换为json响应时,通过利用`encoding/json`包提供的结构体标签,特别是`json:”-“`,可以轻松实现对特定字段的忽略,从而避免敏感数据泄露,确保api…

    2026年5月10日
    000
  • 比特币新手教程 比特币交易平台有哪些

    比特币是一种去中心化的数字货币,基于区块链技术实现点对点交易,具有匿名性、有限发行和不可篡改等特点;新手可通过交易所购买,P2P交易获得比特币,常用平台包括Binance、OKX和Huobi;交易流程包括注册账户、实名认证、绑定支付方式、充值法币并下单购买,可选择市价单或限价单;比特币存储方式有交易…

    2026年5月10日
    000
  • c++中的SFINAE技术是什么_c++模板编程中的SFINAE原理与应用

    SFINAE 是“替换失败不是错误”的原则,指模板实例化时若参数替换导致错误,只要存在其他合法候选,编译器不报错而是继续重载决议。它用于条件启用模板、类型检测等场景,如通过 decltype 或 enable_if 控制函数重载,实现类型特征判断。尽管 C++20 引入 Concepts 简化了部分…

    2026年5月10日
    000
  • Go语言mgo查询构建:深入理解bson.M与日期范围查询的正确实践

    本文旨在解决go语言mgo库中构建复杂查询时,特别是涉及嵌套`bson.m`和日期范围筛选的常见错误。我们将深入剖析`bson.m`的类型特性,解释为何直接索引`interface{}`会导致“invalid operation”错误,并提供一种推荐的、结构清晰的代码重构方案,以确保查询条件能够正确…

    2026年5月10日
    100
  • Golang goroutine与channel调试技巧

    使用go run -race检测数据竞争,结合runtime.NumGoroutine监控协程数量,通过pprof分析阻塞调用栈,利用select超时避免永久阻塞,有效排查goroutine泄漏、死锁和数据竞争问题。 Go语言的goroutine和channel是并发编程的核心,但它们也带来了调试上…

    2026年5月10日
    000
  • 使用 Jupyter Notebook 进行探索性数据分析

    Jupyter Notebook通过单元格实现代码与Markdown结合,支持数据导入(pandas)、清洗(fillna)、探索(matplotlib/seaborn可视化)、统计分析(describe/corr)和特征工程,便于记录与分享分析过程。 Jupyter Notebook 是进行探索性…

    2026年5月10日
    000
  • 《魔兽世界》将于6月11日开启国服回归技术测试

    《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试

    《%ign%ignore_a_1%re_a_1%》官方宣布,将于6月11日开启国服回归技术测试,时间为7天,并称可以在6月内正式开服,玩家们可以访问官网下载战网客户端并预下载“巫妖王之怒”客户端,技术测试详情见下图。 WordAi WordAI是一个AI驱动的内容重写平台 53 查看详情 以上就是《…

    2026年5月10日 用户投稿
    200
  • 如何在HTML中插入表单元素_HTML表单控件与输入类型使用指南

    HTML表单通过标签构建,包含action和method属性定义数据提交目标与方式,常用input类型如text、password、email等适配不同输入需求,配合label、required、placeholder提升可用性,结合textarea、select、button等控件实现完整交互,是…

    2026年5月10日
    000
  • 创建指定大小并填充特定数据的Golang文件教程

    本文将介绍如何使用Golang创建一个指定大小的文件,并用特定数据填充它。我们将使用 `os` 包提供的函数来创建和截断文件,从而实现快速生成大文件的目的。示例代码展示了如何创建一个10MB的文件,并将其填充为全零数据。掌握这些方法,可以方便地在例如日志系统或磁盘队列等场景中,预先创建测试文件或初始…

    2026年5月10日
    000
  • Python命令怎样使用profile分析脚本性能 Python命令性能分析的基础教程

    使用Python的cProfile模块分析脚本性能最直接的方式是通过命令行执行python -m cProfile your_script.py,它会输出每个函数的调用次数、总耗时、累积耗时等关键指标,帮助定位性能瓶颈;为进一步分析,可将结果保存为文件python -m cProfile -o ou…

    2026年5月10日
    000
  • 如何插入查询结果数据_SQL插入Select查询结果方法

    如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法

    使用INSERT INTO…SELECT语句可高效插入数据,通过NOT EXISTS、LEFT JOIN、MERGE语句或唯一约束避免重复;表结构不一致时可通过别名、类型转换、默认值或计算字段处理;结合存储过程可提升可维护性,支持参数化与动态SQL。 将查询结果数据插入到另一个表中,可以…

    2026年5月10日 用户投稿
    000
  • 使用 WebCodecs VideoDecoder 实现精确逐帧回退

    本文档旨在解决在使用 WebCodecs VideoDecoder 进行视频解码时,实现精确逐帧回退的问题。通过比较帧的时间戳与目标帧的时间戳,可以避免渲染中间帧,从而提高用户体验。本文将提供详细的解决方案和示例代码,帮助开发者实现精确的视频帧控制。 在使用 WebCodecs VideoDecod…

    2026年5月10日
    000
  • Debian Copilot的社区活跃度如何

    debian copilot是codeberg社区维护的ai助手,旨在为debian用户提供服务。尽管搜索结果中没有直接提供关于debian copilot社区支持活跃度的具体数据,但我们可以通过debian社区的整体活跃度和特点来推断其活跃性。 Debian社区的一般情况: Debian拥有详尽的…

    2026年5月10日
    000
  • Discord.py 交互按钮超时与持久化解决方案

    本教程旨在解决Discord.py中交互按钮在一段时间后出现“This Interaction Failed”错误的问题。我们将深入探讨视图(View)的超时机制,并提供通过正确设置timeout参数以及利用bot.add_view()方法实现按钮持久化的具体方案,确保您的机器人交互功能稳定可靠,即…

    2026年5月10日
    000
  • JavaScript 动态菜单点击高亮效果实现教程

    本教程详细介绍了如何使用 JavaScript 实现动态菜单的点击高亮功能。通过事件委托和状态管理,当用户点击菜单项时,被点击项会高亮显示(绿色),同时其他菜单项恢复默认样式(白色)。这种方法避免了不必要的DOM操作,提高了性能和代码可维护性,确保了无论点击方向如何,功能都能稳定运行。 动态菜单高亮…

    2026年5月10日
    200
  • c++如何实现UDP通信_c++基于UDP的网络通信示例

    UDP通信基于套接字实现,适用于实时性要求高的场景。1. 流程包括创建套接字、绑定地址(接收方)、发送(sendto)与接收(recvfrom)数据、关闭套接字;2. 服务端监听指定端口,接收客户端消息并回传;3. 客户端发送消息至服务端并接收响应;4. 跨平台需处理Winsock初始化与库链接,编…

    2026年5月10日
    000
  • JavaScript函数中插入加载动画(Spinner)的正确方法

    本文旨在解决在JavaScript函数中插入加载动画(Spinner)时遇到的异步问题。通过引入async/await和Promise.all,确保在数据处理完成前后正确显示和隐藏加载动画,提升用户体验。我们将提供两种实现方案,并详细解释其原理和优势。 在Web开发中,当执行耗时操作时,显示加载动画…

    2026年5月10日
    000
  • 使用 Pydantic v2 实现条件性必填字段

    本文介绍了如何在 Pydantic v2 模型中实现条件性必填字段。通过自定义验证器,可以根据模型中其他字段的值来动态地控制某些字段是否为必填项,从而满足 API 交互中数据验证的复杂需求。本文提供了一个具体的示例,展示了如何确保模型中至少有一个字段被赋值。 在 Pydantic v2 中,虽然没有…

    2026年5月10日
    000
  • 三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布

    三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布

    6 月 15 日消息,据博主@肥威 今日爆料,搭载骁龙 8 Gen 3 领先版%ign%ignore_a_1%re_a_1%的新机即将发布,把之前的 for Galaxy 改成“for Everybody”。 Pic Copilot AI时代的顶级电商设计师,轻松打造爆款产品图片 158 查看详情 …

    2026年5月10日 用户投稿
    000
  • 动态更新圆形进度条:JavaScript成绩计算器集成指南

    本文档旨在指导开发者如何将JavaScript成绩计算系统与动态圆形进度条集成,实现可视化展示平均成绩。我们将详细讲解如何修改现有的JavaScript代码,使其在计算出平均分后,能够动态更新圆形进度条的进度,从而提供更直观的用户体验。本文档包含详细的代码示例和注意事项,帮助开发者轻松实现这一功能。…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信