我偶然发现了以下
const myObject = new Object();
myObject['test'] = 'hello';
calc(myObject['test']);
function calc(x: number) {
console.log(x * 10);
}
这是一个非常简单的案例。
我的期望是TypeScript至少会在编译时抱怨它找不到具体类型,但calc
需要一个数字。
相反,TypeScript根本不会抱怨,而且在控制台中会有NaN
。
使用angular 4和路由数据时,我首先注意到了这种行为。
const routes: Routes = [
{
path: '**',
data: [{error: new ApplicationError('http-status-404', '', HttpErrorStatus.NotFound)}],
component: ApplicationErrorComponent,
resolve: {
error: ApplicationErrorResolve
}
}
];
@Injectable()
export class ApplicationErrorResolve implements Resolve<ApplicationError> {
constructor(private applicationErrorHandler: ApplicationErrorHandler) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): ApplicationError {
if (route.data != null && route.data[0]['error'] instanceof ApplicationError) {
this.applicationErrorHandler.addError(route.data[0]);
return route.data[0];
}
return null;
}
}
// signature of applicationErrorHandler.addError
addError(error: ApplicationError, navigateToErrorPage: boolean = true) {
}
如代码所示,我的对象ApplicationError
将位于route.data[0].error
而不是route.data[0]
。
但是TypeScript并没有抱怨,在运行期间我只会有完全错误的对象(类型)
我能做些什么吗(除了手动检查instanceof或类似内容)? 像某种警卫或打字稿一样(如--strictNullCheck)?
来自c#背景,这让我感到非常惊讶(并且有点担心)
修改
感谢Saravana的第一部分(简单示例)有效。
但是一旦我使用数组,它就会再次失败。即使有noImplictAny = true
const myArray = new Array<any>();
myArray[0] = { name: 'test'};
myArray[1] = { name: 1} ;
// TypeScript doesn't complain
this.calc(myArray[0]);
// TypeScript doesn't complain
this.calc(myArray[0].ImActuallyNotPresent);
function calc(x: number) {
console.log(x * 10);
}
我不明白。为什么这样做?
我知道它与any
有关,但为什么myArray
的定义会取代我的方法签名?
这对我来说没什么意义,给人一种虚假的安全感。
有没有解决这个问题?
答案 0 :(得分:0)
您需要在"noImplicitAny": true
中设置tsconfig.json
或将--noImplicitAny
标记传递给编译器以捕获这些问题。
如果您已启用noImplicitAny
,编译器将检查myObject['test']
对calc
的类型。由于它已关闭myObject['test']
的类型被视为any
,它会禁用所有类型检查,允许将其传递给calc
。
使用"noImplicitAny": true
,您的示例将引发以下错误:
元素隐式具有“任意”类型,因为类型“对象”没有 索引签名。
TypeScript编译器选项:https://www.typescriptlang.org/docs/handbook/compiler-options.html
当您在示例中执行const myArray = new Array<any>();
时,您告诉编译器myArray
可以保存任何数组。编译器唯一要验证的是myArray
是一个数组。数组的内容可以是任何内容。这就是为什么myArray[0].ImActuallyNotPresent
不会抛出任何错误的原因。因为你告诉编译器没有关于数组内容的信息。
要确保对数组内容进行类型检查,请提供数组的类型信息:
interface MyArrayContent {
someString: string;
someNumber: number
}
const myArray = new Array<MyArrayContent>();
myArray[0] = { someString: 'test', someNumber: 1 };
myArray[1] = { someString: "test2", someNumber: 2};
calc(myArray[0]); // Error
calc(myArray[0].ImActuallyNotPresent); // Error
calc(myArray[0].someString); // Error
calc(myArray[0].someNumber); // No error
function calc(x: number) {
console.log(x * 10);
}
any
是TypeScript绕过所有类型检查并进入完整JS模式并忽略所有编译时检查的方法 - 其中包括验证calc
是否有number
参数。我理解这种困惑。在C#这样的语言中,即使所有object
都是string
s,当方法期望string
没有强制转换时,也无法传递object
类型的变量。但是如果你认为any
是“在使用这个变量的地方禁用所有类型检查”的同义词,那就更有意义了。
any
文档:https://www.typescriptlang.org/docs/handbook/basic-types.html#any