当前位置: 代码网 > it编程>编程语言>Javascript > Typescript extends 关键字继承类型约束及条件类型判断实现示例解析

Typescript extends 关键字继承类型约束及条件类型判断实现示例解析

2024年05月15日 Javascript 我要评论
引言最近团队新增了一个hc,面试候选人的过程中,看他简历,履历很牛逼,并且里面写的精通typescript。我想那我们就问一个很基础的问题吧,你了解typscript的extends关键字吗?它都会在

引言

最近团队新增了一个 hc,面试候选人的过程中,看他简历,履历很牛逼,并且里面写的精通 typescript

我想那我们就问一个很基础的问题吧,你了解 typscript 的 extends 关键字吗?它都会在那几个场景下使用?

结果很失望,即使在我写出了 extends 的使用方式时,这位哥们还没想起怎么用,只能含糊其辞。

我赶紧换了一个问题,避免太尴尬:你了解 ts 工具类型 exclude 与 omit 的使用吗?及它们两个的区别?

这哥们还是不会~

不出意外的一面就挂了,说这个事的原因是,现在经济下行、市场上是狼多肉少,大家一定要珍惜面试机会,实事求是,平时多积累、多梳理,战时抓机会、少冷场啊。

好了下面说正事。

extends 关键字实现继承

如果你有看过 typescript 官方文档,起码熟悉这两个:

  • extends 关键字可以实现 interface 类型的扩展,

    • 这个也是 interface 与 type 类型别名实现扩展的区别之一,类型别名通过 & 交叉类型来实现类型扩展
  • extends 关键字可用于 class 的继承

比如定义个 animal 接口

interface animal {
  name: string
}
interface person extends animal {
  level: number
}
const person: person = {
  name: 'perter',
  level: 1
}
interface dog extends animal {
  leg: number
}
const dog: dog = {
  name: 'bagong',
  leg: 4
}

如果使用 class

class animal {
  move() {
    console.log("moving along!");
  }
}
class person extends animal {
  talk(info: string) {
    console.log(info)
  }
}
const person = new person();
// base class method
person.move();
// derived class method
person.talk('hello world')
class dog extends animal {
  woof(times: number) {
    for (let i = 0; i < times; i++) {
      console.log("woof!");
    }
  }
}
const d = new dog();
// base class method
d.move();
// derived class method
d.woof(3);

这种方式就是在践行 extends 单词的本意 扩展

extends 实现类型约束

很贴切的列子就是 typescript 的工具类型 pick,可以通过从一个 类型中选取一组属性集合来构造一个新的类型。

接下来让我们实现下:

type mypick<t, keys> = {
  [key in keys]: t[key] // error: type 'key' cannot be used to index type 't'.
}

如果你直接这么写,ts 编译器肯定是要报错的。因为用户传入的属性集合中很可能在 t 中不存在!

所以我们需要对属性集合 keys 进行约束,约束其必须为 t 的属性集合子集。

type mypick<t, keys extends keyof t> = {
  [key in keys]: t[key]
}
// 使用
interface todo {
  title: string;
  description: string;
  completed: boolean;
}
type todopreview = mypick<todo, "title" | "completed">;
const todo: todopreview = {
  title: "clean room",
  completed: false,
};
todo; // ok

这是第二种方式,对泛型参数进行约束。

extends 实现条件类型判断

在 typescript 类型体操基础动作中,有一种动作叫:条件类型,条件类型主要用于去判断两个类型之间的关系。

建议阅读 

比如工具类型 exclude 的实现,就是基于条件类型:

type myexclude<t, key> =  t extends key ? never : t

可以实现基于联合类型 key ,排除联合类型 t 中匹配的类型。

type t0 = myexclude<"a" | "b" | "c", "a">; // type t0 = "b" | "c"
type t1 = myexclude<"a" | "b" | "c", "a" | "b">; // type t1 = "c"

在多数工具类型中,都用到了这个特性,最常见的就是递归类型。递归三要素之一就是要有终止条件,而我们就可以通过 extends 实现终止条件的判断。

比如

  • 实现一个 deepreadonly 工具类型,可以做到将对象类型的所有属性转为只读:
type deepreadonly<t> = keyof t extends never ? t : {
  readonly [key in keyof t]: deepreadonly<t[key]> : t[key]
}
  • 实现一个 trimleft ,可以实现移除字符串类型的左边空格:
type space = ' ' | '\n' | '\t'
type trimleft<s extends string> = s extends `${space}${infer r}` ? trimleft<r> : s
type trimed = trimleft<'  hello world  '> // expected to be 'hello world  '
  • 实现一个 kebabcase 类型,可以实现对字符串类型的驼峰转横杠:
type kebabcase<t extends string> = t extends `${infer f}${infer r}` ? r extends uncapitalize<r> ?  `${uncapitalize<f>}${kebabcase<r>}`
  : `${uncapitalize<f>}-${kebabcase<r>}`
  : t;
type foobarbaz = kebabcase<"foobarbaz">;
const foobarbaz: foobarbaz = "foo-bar-baz";
type donothing = kebabcase<"do-nothing">;
const donothing: donothing = "do-nothing";

是不是很有意思?

最后

恭喜你,通过短短几分钟,有进步了一丢丢。

参考

以上就是typescript extends 关键字的三个妙用的详细内容,更多关于typescript extends 关键字的资料请关注代码网其它相关文章!

(0)

相关文章:

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

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com