如下代码,is用法我看的文章都是传一个参数,然后尝试用两个,遇到几个疑问
- 发现下图的isP函数不管第一个参数是true还是false,liney的c都是string,linez都是number,
- 如果我把if部分放到外面,即使用{}包起来,c会提示是never类型,放到函数里c就是联合类型
假设变量m是布尔,n是联合类型o|p,当m为true,n是o类型,否则是p类型,那么在不用as断言的情况下如何根据m来收窄n的类型
const isP = (a: boolean, b: number | string): b is string => { return a == true; }; let c: number | string = 3; const t = () => { if (isP(true, c)) { // x console.log(c.length); // y } else{ console.log(c.toFixed(2)); // z } console.log(c); };
对于第一条:
这个函数的意思是:如果第一个参数a是真值,那么b是一个字符串类型的变量。因此isP(true, c)进入到if的真分支,这里c认为是一个字符串,所以可以去访问length属性。反之假分支中c认为是一个number类型的值,可以使用toFixed方法。
对于第二条:
c放到函数t里面声明,c仅存活于t函数中,可以明确知道要么对c进行了string类型的赋值,要么进行了number类型的赋值,所以可以直接推断c的类型。let c: number | string = 3;这句话一旦赋值,c暂时就是number类型,isP(true, c)会导致c明明是number,非说他是字符串,就产生了never。
对于第三条:
最好还是不要用值来决定或影响类型。变量的值是运行时的概念,ts的类型是编译期的概念。联合类型想要取其一,要么是类型系统帮你推断好是什么类型(c放在函数t里面声明赋值),要么就是没法预知类型,只能靠代码逻辑判断类型(c放在函数t外面声明赋值)。对于前者,是因为类型系统可以帮你推测出来,你不要在过多的担心。但是对于后者,因为c可能是不可预知的,比如是从某个接口里读的数据,接口声明返回值也是联合类型的,这你怎么判断,还是得靠代码逻辑才能进入对的分支。不知道这么说有没有覆盖你的场景。但是真的别把变量的值和变量的类型揉在一起。