添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
GitHub
关注公众号
关注公众号
与我交流
购买此书
关注公众号
与我交流
购买此书

类型保护

类型保护允许你使用更小范围下的对象类型。

typeof

TypeScript 熟知 JavaScript 中 instanceof typeof 运算符的用法。如果你在一个条件块中使用这些,TypeScript 将会推导出在条件块中的的变量类型。如下例所示,TypeScript 将会辨别 string 上是否存在特定的函数,以及是否发生了拼写错误:

function doSome(x: number | string) {
  if (typeof x === 'string') {
    // 在这个块中,TypeScript 知道 `x` 的类型必须是 `string`
    console.log(x.




    
subtr(1)); // Error: 'subtr' 方法并没有存在于 `string` 上
    console.log(x.substr(1)); // ok
  x.substr(1); // Error: 无法保证 `x` 是 `string` 类型

instanceof

这有一个关于 class instanceof 的例子:

class Foo {
  foo = 123;
  common = '123';
class Bar {
  bar = 123;
  common = '123';
function doStuff(arg: Foo | Bar) {
  if (arg instanceof Foo) {
    console.log(arg.foo); // ok
    console.log(arg.bar); // Error
  if (arg instanceof Bar) {
    console.log(arg.foo); // Error
    console.log(arg.bar); // ok
doStuff(new Foo());
doStuff(new Bar());

TypeScript 甚至能够理解 else 。当你使用 if 来缩小类型时,TypeScript 知道在其他块中的类型并不是 if 中的类型:

class Foo {
  foo = 123;
class Bar {
  bar = 123;
function doStuff(arg: Foo | Bar) {
  if (arg instanceof Foo) {
    console.log(arg.foo); // ok
    console.log(arg.bar); // Error
  } else {
    // 这个块中,一定是 'Bar'
    console.log(arg.foo); // Error
    console.log(arg.bar); // ok
doStuff(new Foo());
doStuff(new Bar());

in

in 操作符可以安全的检查一个对象上是否存在一个属性,它通常也被作为类型保护使用:

interface A {
  x: number;
interface B {
  y: string;
function doStuff(q: A | B) {
  if ('x' in q) {
    // q: A
  } else {
    // q: B

字面量类型保护

当你在联合类型里使用字面量类型时,你可以检查它们是否有区别:

type Foo = {
  kind: 'foo'; // 字面量类型
  foo: number;
type Bar = {
  kind: 'bar'; // 字面量类型
  bar: number;
function doStuff(arg: Foo | Bar) {
  if (arg.kind === 'foo') {
    console.log(arg.foo); // ok
    console.log(arg.bar); // Error
  } else {
    // 一定是 Bar
    console.log(arg.foo); // Error
    console.log(arg.bar); // ok

使用定义的类型保护

JavaScript 并没有内置非常丰富的、运行时的自我检查机制。当你在使用普通的 JavaScript 对象时(使用结构类型,更有益处),你甚至无法访问 instanceof typeof 。在这种情景下,你可以创建 用户自定义的类型保护函数 ,这仅仅是一个返回值为类似于 someArgumentName is SomeType 的函数,如下:

// 仅仅是一个 interface
interface Foo {
  foo: number;
  common: string;
interface Bar {
  bar: number;
  common: string;
// 用户自己定义的类型保护!
function isFoo(arg: Foo | Bar): arg is Foo {
  return (arg as Foo).foo !== undefined;
// 用户自己定义的类型保护使用用例:
function doStuff(arg: Foo | Bar) {
  if (isFoo(arg)) {
    console.log(arg.foo); // ok
    console.log(arg.bar); // Error
  } else {
    console.log(arg.foo); // Error
    console.log(arg.bar); // ok
doStuff({ foo: 123, common: '123' });
doStuff({ bar: 123, common: '123' });