typescript-tutorial
typescript-tutorial copied to clipboard
类型断言
https://ts.xcatliu.com/basics/type-assertion.html
类型断言和类型声明那边还是没懂
@guimeisang 类型断言和类型声明那边还是没懂
哪句话不懂?能具体说下吗?
这个兼容的含义有点抽象,然后也不知道 "知道了它们的核心区别,就知道了类型声明是比类型断言更加严格的。"这个结论是怎么推导出来的
这个其实很基础,我感觉能懂
@guimeisang
这个兼容的含义有点抽象,然后也不知道 "知道了它们的核心区别,就知道了类型声明是比类型断言更加严格的。"这个结论是怎么推导出来的
a能干的,b不能干。所以对b更加严格
“兼容”这个词不太容易理解,建议改成“包括”。 父类包括子类(Animal包括Cat),但子类不包括父类(Cat不包括Animal)。 联合类型(number|string)包括具体类型(number),但具体类型(number)不包括联合类型(number|string)
能说说断言一般用在什么地方吗?假如A变量为number类型,B变量为string类型,A.length会提示报错,所以用了A as B来使A.length不提示报错,我看教程理解是这个意思,不是很明白这个操作有什么用?运行不还是会报错吗?感觉有点像try{}catch{},但是又不是,存在肯定有它的意义,能举一些例子让我们这些入门的人明白断言具体什么情况下用吗?
interface Cat { name: string; run(): void; } interface Fish { name: string; swim(): void; }
类似于 run(): void;这种在接口中的定义形式的含义似乎在前面的小节中都没有讲解。是说run属性是一个返回void值的函数对么?是否等价于: interface Cat { name: string; run:()=> void }
我觉得似乎只有第一种:将一个联合类型断言为其中一个类型 是有意义的。其他的用途我看不到意义
前面说到接口定义了对象的结构,并且属性不能多也不能少,那么这种断言的意义就很让人疑惑。举例来说: interface Animal { name: string; } interface Cat { name: string; run(): void; }
const animal: Animal = { name: 'tom' }; let tom = animal as Cat;
因为animal只有name属性,而cat要求有两个属性,那么与你之前属性不能多也不能少这个说法相悖了吗? 这节的标题是:类型断言(Type Assertion)可以用来手动指定一个值的类型。 可是假设一个值本身就符合一个接口的描述了,那么断言成任意属性数量与该接口不同的新接口不都应该违背了接口的要求吗?
类型断言的目的就是让编译通过吗
"兼容"这个词措给人的第一印象是包含关系
,是一个动词,Handbook 中多用的是 compatible
和 compatibility
,感觉语义上还是有些区别的,所以看上去会比较抽象
@zhushuanghui 类型断言的目的就是让编译通过吗
是
还是搞不懂类型系统的,建议还是看看一门最简单的强类型语言就什么都明白了,比如C语言或者Java,类型断言只是个编译器的临时伪装,并不是真正的类型声明。
懂是能动,写的时候就不知道还记得多少了0.0
interface Animal {
name: string;
}
interface Cat {
name: string;
run(): void;
}
let tom: Cat = {
name: 'Tom',
run: () => { console.log('run') }
};
let animal: Animal = tom;
这一段没太看懂,为什么Cat类型的tom可以赋值给animal,明明Animal没有Cat的run方法啊,这不是应该报错吗?
[结构类型系统(TODO)][]、[类型兼容性(TODO)][] 这两个在哪儿呀
@a982246809 还没写呢,所以是 TODO 😂
@zhushuanghui 类型断言的目的就是让编译通过吗
是个 我感觉就是强行指定 譬方说 cat 和dog 都继承了animals 但是你在实际代码中 很明确这里返回的就会cat 那么久断言一下 然后直接调用cat的方法. 其他的用处具体没理解 感觉花里胡哨一大堆 实际上没有用的到的地方
@liantianyun 我觉得似乎只有第一种:将一个联合类型断言为其中一个类型 是有意义的。其他的用途我看不到意义
前面说到接口定义了对象的结构,并且属性不能多也不能少,那么这种断言的意义就很让人疑惑。举例来说: interface Animal { name: string; } interface Cat { name: string; run(): void; }
const animal: Animal = { name: 'tom' }; let tom = animal as Cat;
因为animal只有name属性,而cat要求有两个属性,那么与你之前属性不能多也不能少这个说法相悖了吗? 这节的标题是:类型断言(Type Assertion)可以用来手动指定一个值的类型。 可是假设一个值本身就符合一个接口的描述了,那么断言成任意属性数量与该接口不同的新接口不都应该违背了接口的要求吗?
同感,我也有点这个疑问。
@qq1090871975 能说说断言一般用在什么地方吗?假如A变量为number类型,B变量为string类型,A.length会提示报错,所以用了A as B来使A.length不提示报错,我看教程理解是这个意思,不是很明白这个操作有什么用?运行不还是会报错吗?感觉有点像try{}catch{},但是又不是,存在肯定有它的意义,能举一些例子让我们这些入门的人明白断言具体什么情况下用吗?
假设你有一个泛型数组。Array<Animal> animals, 在循环中,你希望判断一下animal的类型是不是cat, 然后执行cat类的特殊方法爬树,if( oAnimal instanceOf Cat) { let oCat = oAnimal as Cat; oCat.ClimbTree() }
@leoying-studio 这个其实很基础,我感觉能懂
我不要你觉得,我要我觉得
@qq1090871975 能说说断言一般用在什么地方吗?假如A变量为number类型,B变量为string类型,A.length会提示报错,所以用了A as B来使A.length不提示报错,我看教程理解是这个意思,不是很明白这个操作有什么用?运行不还是会报错吗?感觉有点像try{}catch{},但是又不是,存在肯定有它的意义,能举一些例子让我们这些入门的人明白断言具体什么情况下用吗?
在两个类型没有兼容的情况下,是不能进行断言的。就像说的 string as number会报错。 我有时候想偷懒的时候就会用到断言。 eg:
interface IForm {
id: number;
name: string;
}
const [form, setFrom] = useState<IForm>({id: 0,name: ''}); //不使用断言,需要初始化值,否则后面用到form的地方会报错
2. const [form, setForm] = useState({} as IForm); // 明确{}对象是IForm类型,后面使用form也不会报错
@JiXianGu
interface Animal { name: string; } interface Cat { name: string; run(): void; } let tom: Cat = { name: 'Tom', run: () => { console.log('run') } }; let animal: Animal = tom;
这一段没太看懂,为什么Cat类型的tom可以赋值给animal,明明Animal没有Cat的run方法啊,这不是应该报错吗?
这就相当于Cat类型是子类,Animal是父类,run方法是子类自定义的方法
简单问题复杂化,直接泛型不就ok了
可否这样理解:类型声明是在变量被赋值之前对变量做约束;类型断言是在变量被使用之前对变量做约束?
@liantianyun 我觉得似乎只有第一种:将一个联合类型断言为其中一个类型 是有意义的。其他的用途我看不到意义
前面说到接口定义了对象的结构,并且属性不能多也不能少,那么这种断言的意义就很让人疑惑。举例来说: interface Animal { name: string; } interface Cat { name: string; run(): void; }
const animal: Animal = { name: 'tom' }; let tom = animal as Cat;
因为animal只有name属性,而cat要求有两个属性,那么与你之前属性不能多也不能少这个说法相悖了吗? 这节的标题是:类型断言(Type Assertion)可以用来手动指定一个值的类型。 可是假设一个值本身就符合一个接口的描述了,那么断言成任意属性数量与该接口不同的新接口不都应该违背了接口的要求吗?
同感 不知道里面是不是还有什么猫腻
@blanklong28
@qq1090871975 能说说断言一般用在什么地方吗?假如A变量为number类型,B变量为string类型,A.length会提示报错,所以用了A as B来使A.length不提示报错,我看教程理解是这个意思,不是很明白这个操作有什么用?运行不还是会报错吗?感觉有点像try{}catch{},但是又不是,存在肯定有它的意义,能举一些例子让我们这些入门的人明白断言具体什么情况下用吗?
在两个类型没有兼容的情况下,是不能进行断言的。就像说的 string as number会报错。 我有时候想偷懒的时候就会用到断言。 eg:
interface IForm { id: number; name: string; } const [form, setFrom] = useState<IForm>({id: 0,name: ''}); //不使用断言,需要初始化值,否则后面用到form的地方会报错 2. const [form, setForm] = useState({} as IForm); // 明确{}对象是IForm类型,后面使用form也不会报错
又学到了~
@lhmcn “兼容”这个词不太容易理解,建议改成“包括”。 父类包括子类(Animal包括Cat),但子类不包括父类(Cat不包括Animal)。 联合类型(number|string)包括具体类型(number),但具体类型(number)不包括联合类型(number|string)
Animal
只有name
,而Cat
有name
和run()
,这里我的理解应该是Cat
包括Animal
,不应该是多的包括少的嘛,但我这样的理解就成了子类包括父类了。。。应该也不对