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

相关推荐

  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200
  • 为什么我的 Safari 自定义样式表在百度页面上失效了?

    为什么在 Safari 中自定义样式表未能正常工作? 在 Safari 的偏好设置中设置自定义样式表后,您对其进行测试却发现效果不同。在您自己的网页中,样式有效,而在百度页面中却失效。 造成这种情况的原因是,第一个访问的项目使用了文件协议,可以访问本地目录中的图片文件。而第二个访问的百度使用了 ht…

    2025年12月24日
    000
  • 如何用前端实现 Windows 10 设置界面的鼠标移动探照灯效果?

    如何在前端实现 Windows 10 设置界面中的鼠标移动探照灯效果 想要在前端开发中实现 Windows 10 设置界面中类似的鼠标移动探照灯效果,可以通过以下途径: CSS 解决方案 DEMO 1: Windows 10 网格悬停效果:https://codepen.io/tr4553r7/pe…

    2025年12月24日
    000
  • 使用CSS mask属性指定图片URL时,为什么浏览器无法加载图片?

    css mask属性未能加载图片的解决方法 使用css mask属性指定图片url时,如示例中所示: mask: url(“https://api.iconify.design/mdi:apple-icloud.svg”) center / contain no-repeat; 但是,在网络面板中却…

    2025年12月24日
    000
  • 如何用CSS Paint API为网页元素添加时尚的斑马线边框?

    为元素添加时尚的斑马线边框 在网页设计中,有时我们需要添加时尚的边框来提升元素的视觉效果。其中,斑马线边框是一种既醒目又别致的设计元素。 实现斜向斑马线边框 要实现斜向斑马线间隔圆环,我们可以使用css paint api。该api提供了强大的功能,可以让我们在元素上绘制复杂的图形。 立即学习“前端…

    2025年12月24日
    000
  • 图片如何不撑高父容器?

    如何让图片不撑高父容器? 当父容器包含不同高度的子元素时,父容器的高度通常会被最高元素撑开。如果你希望父容器的高度由文本内容撑开,避免图片对其产生影响,可以通过以下 css 解决方法: 绝对定位元素: .child-image { position: absolute; top: 0; left: …

    2025年12月24日
    000
  • CSS 帮助

    我正在尝试将文本附加到棕色框的左侧。我不能。我不知道代码有什么问题。请帮助我。 css .hero { position: relative; bottom: 80px; display: flex; justify-content: left; align-items: start; color:…

    2025年12月24日 好文分享
    200
  • 前端代码辅助工具:如何选择最可靠的AI工具?

    前端代码辅助工具:可靠性探讨 对于前端工程师来说,在HTML、CSS和JavaScript开发中借助AI工具是司空见惯的事情。然而,并非所有工具都能提供同等的可靠性。 个性化需求 关于哪个AI工具最可靠,这个问题没有一刀切的答案。每个人的使用习惯和项目需求各不相同。以下是一些影响选择的重要因素: 立…

    2025年12月24日
    300
  • 如何用 CSS Paint API 实现倾斜的斑马线间隔圆环?

    实现斑马线边框样式:探究 css paint api 本文将探究如何使用 css paint api 实现倾斜的斑马线间隔圆环。 问题: 给定一个有多个圆圈组成的斑马线图案,如何使用 css 实现倾斜的斑马线间隔圆环? 答案: 立即学习“前端免费学习笔记(深入)”; 使用 css paint api…

    2025年12月24日
    000
  • 如何使用CSS Paint API实现倾斜斑马线间隔圆环边框?

    css实现斑马线边框样式 想定制一个带有倾斜斑马线间隔圆环的边框?现在使用css paint api,定制任何样式都轻而易举。 css paint api 这是一个新的css特性,允许开发人员创建自定义形状和图案,其中包括斑马线样式。 立即学习“前端免费学习笔记(深入)”; 实现倾斜斑马线间隔圆环 …

    2025年12月24日
    100

发表回复

登录后才能评论
关注微信