user defined type guards [typescript]

戏子无情 提交于 2019-12-11 04:30:25

问题


With TypeScript 1.6 is it possible to write functions to check objects against interfaces. (Below is the anncouncement from MSDN and how to use it.)

My question targets the return expression return a.name === 'kitty';:

  1. Plays it an role?
  2. Must all cats called kitty?

User defined type guards

[http://blogs.msdn.com/b/typescript/archive/2015/09/16/announcing-typescript-1-6.aspx]

In earlier versions of TypeScript, you could use if statements to narrow the type. For example, you could use:

if (typeof x === "number") { … }

This helped type information flow into common ways of working with types at runtime (inspired by some of the other projects doing typechecking of JS). While this approach is powerful, we wanted to push it a bit further. In 1.6, you can now create your own type guard functions:

interface Animal {name: string; } 
interface Cat extends Animal {
  meow(); 
}

function isCat(a: Animal): a is Cat {
  return a.name === 'kitty'; 
}

var x: Animal;

if(isCat(x)) {
  x.meow(); // OK, x is Cat in this block
}

This allows you to work with not only typeof and instanceof checks, which need a type that JavaScript understands, but now you can work with interfaces and do custom analysis. Guard functions are denoted by their “a is X” return type, which returns boolean and signals to the compiler if what the expected type now is.


回答1:


Consider your example

interface Animal {name: string; } - an interface
interface Cat extends Animal { - an implementation
  meow(); 
}

function isCat(a: Animal): a is Cat {
  return a.name === 'kitty'; // your special checking you can replace it with any other checking expression
}

var x: Animal;

if(isCat(x)) {
  x.meow(); // OK, x is Cat in this block
}

This example show, that now, we can use expression like a is Cat and in the follow block, where checking has been already used, type of a would be Cat. The return a.name === 'kitty'; expression you can replace with

function isCat(a: Animal): a is Cat {
  return a["meow"] != undefined; // it also would be indicate that the animal is Cat
}

and it would be work.

Even you can replace it with this too

function isCat(a: Animal): a is Cat {
      return true;
}

I have prepared example for you, you can play with it.

Conclusions:

  1. Expression a is Cat provide same effect as a instanceof SomeClass, but first one is customizable checking instead of last one, and last one does not work with interfaces.
  2. Your checking function can contain any code - it is your choice
  3. This future give us possibility to check if instance is inctanceof interface

Update

  1. Plays it an role?
    • Yes, it plays. a.name === 'kitty' - this expression show the logic of checking that given animal IS - Cat, so, here you can provide any boolean expression that check that given animal is Cat even you can return just true or false;
  2. Must all cats called kitty?
    • No. It is up to you. In function isCat you can provide any logic that ensure that given animal is of type Cat



回答2:


Your questions regarding return a.name === 'kitty';:

1)Does it plays a role?
Yes, the return value determines whether the type guard passes or fails.

2)Must all cats called kitty?
Yes, in this case, all cats must be called Kitty.

What it comes down to, it this was not a very good example.

A better one would be...

class Animal {name: string; type: string; }
class Cat extends Animal {
  type: string = "Cat";
  meow() {}; 
}

function isCat(a: Animal): a is Cat {
  return a.type === 'Cat'; // your special checking you can replace it with any other checking expression
}

var x: Animal = new Cat();

if(isCat(x)) {
  x.meow(); // OK, x is Cat in this block
}

see JSFiddle.



来源:https://stackoverflow.com/questions/32713452/user-defined-type-guards-typescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!