如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。
类型推论
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
事实上,它等价于:
let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查:
let myFavoriteNumber;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
类型断言
类型断言(Type Assertion)可以用来手动指定一个值的类型
类型断言的用途:
将一个联合类型断言为其中一个类型
当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型中共有的属性或方法:
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
function getName(animal: Cat | Fish) {
return animal.name;
}
而有时候,我们确实需要在还不确定类型的时候就访问其中一个类型特有的属性或方法,比如:
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
function isFish(animal: Cat | Fish) {
if (typeof animal.swim === 'function') {
return true;
}
return false;
}
// index.ts:11:23 - error TS2339: Property 'swim' does not exist on type 'Cat | Fish'.
// Property 'swim' does not exist on type 'Cat'.
上面的例子中,获取 animal.swim 的时候会报错。
此时可以使用类型断言,将 animal 断言成 Fish:
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
function isFish(animal: Cat | Fish) {
if (typeof (animal as Fish).swim === 'function') {
return true;
}
return false;
}
这样就可以解决访问 animal.swim 时报错的问题了。
将一个父类断言为更加具体的子类
当类之间有继承关系时,类型断言也是很常见的:
class ApiError extends Error {
code: number = 0;
}
class HttpError extends Error {
statusCode: number = 200;
}
function isApiError(error: Error) {
if (typeof (error as ApiError).code === 'number') {
return true;
}
return false;
}
上面的例子中,我们声明了函数 isApiError,它用来判断传入的参数是不是 ApiError 类型,为了实现这样一个函数,它的参数的类型肯定得是比较抽象的父类 Error,这样的话这个函数就能接受 Error 或它的子类作为参数了。
但是由于父类 Error 中没有 code 属性,故直接获取 error.code 会报错,需要使用类型断言获取 (error as ApiError).code。
大家可能会注意到,在这个例子中有一个更合适的方式来判断是不是 ApiError,那就是使用 instanceof:
class ApiError extends Error {
code: number = 0;
}
class HttpError extends Error {
statusCode: number = 200;
}
function isApiError(error: Error) {
if (error instanceof ApiError) {
return true;
}
return false;
}
上面的例子中,确实使用 instanceof 更加合适,因为 ApiError 是一个 JavaScript 的类,能够通过 instanceof 来判断 error 是否是它的实例。
如果是接口,此时就只能用类型断言,通过判断是否存在 code 属性,来判断传入的参数是不是 ApiError 了:
interface ApiError extends Error {
code: number;
}
interface HttpError extends Error {
statusCode: number;
}
function isApiError(error: Error) {
if (typeof (error as ApiError).code === 'number') {
return true;
}
return false;
}
将任何一个类型断言为 any
(window as any).foo = 1;
将 any 断言为一个具体的类型
类型别名
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') {
return n;
} else {
return n();
}
}
上例中,我们使用 type 创建类型别名。
类型别名常用于联合类型。
参考
TypeScript 入门教程 - ts.xcatliu.com/
TypeScript 官网 - www.typescriptlang.org/
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!