使用索引签名比使用AngularJs更令人担忧,但这是一个我认为需要以某种方式解决TypeScript类型的关键问题。
除了TypeScript 2.4的弱类型之外,@ types / angularjs IController开始抱怨弱类型,而修复(此时唯一可能的修复)是添加索引签名,如下所述:
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/17257 https://github.com/DefinitelyTyped/DefinitelyTyped/pull/17303
但是在此更改之前,TypeScript错误将有助于确保当您使用对象中的属性键入IController时,它会(恰当地)抱怨您错过了定义属性,这是使TypeScript成为非常有用的事情之一伟大的语言(至少IMO)。
这是使用简化的AngularJs 1.5组件的直接示例:
let MyComponent = function(): angular.IComponentOptions {
return {
bindings: {},
controller: MyController,
controllerAs: 'vm',
}
}
interface IController extends angular.IController {
x: string;
}
function MyController(this: IController) {
let vm = this;
vm.x = "foo"; // OK
vm.x = 1; // ERROR: As expected due to the definition - great
// This next line would have complained before this,
// now it will let it thru unscathed, same with functions,
// arrays, etc. - this is the problem
vm.y = "bar"; // OK now, ERROR before
}
是否有办法允许AngularJs的类型避免弱类型关注(这是有意义的),同时仍然允许正确检查子类型?
我个人觉得应该尽可能避免索引签名,因为这个问题,并不是避免编译错误的好方法(虽然目前可能是唯一的方法)。
由于
答案 0 :(得分:0)
您可以使用映射类型解决它,它允许您定义一个强大的接口,但使用Partial
映射类型使其属性可选...
// We don't want a weak type... or an index signature...
interface WeakType {
x?: string;
}
interface StrongType {
x: string;
}
type PartialStrongType = Partial<StrongType>;
function doSomething(options: PartialStrongType) {
return options.x || '';
}
doSomething({}); // OK
doSomething({ x: 'str' }); // OK
doSomething({ x: 1 }); // x can't be a number
doSomething({ y: 'str' }); // hey, you typed 'y', did you mean 'x'
答案 1 :(得分:0)
我能提出的唯一解决方案是需要更改本地角度类型定义文件(或者可能是上游推送)。现在,角度中IController
的定义看起来像这样:
interface IController {
$onInit?(): void;
$doCheck?(): void;
$onChanges?(onChangesObj: IOnChangesObject): void;
$onDestroy?(): void;
$postLink?(): void;
[s: string]: any;
}
也许应该改为:
interface IControllerWeak {
$onInit?(): void;
$doCheck?(): void;
$onChanges?(onChangesObj: IOnChangesObject): void;
$onDestroy?(): void;
$postLink?(): void;
}
interface IController extends IControllerWeak {
[s: string]: any;
}
对于下游的每个人来说,这应该完全相同,但它现在为您提供IControllerWeak
的引用,IController
只有IController
而没有索引签名。在大多数(所有?)案例中,要求IControllerWeak
的内容会接受IControllerWeak
,反之亦然。
所以现在你可以使用必需的属性扩展interface IController extends angular.IControllerWeak {
x: string;
}
function MyController(this: IController) {
let vm = this;
vm.x = "foo"; // OK
vm.x = 1; // ERROR
vm.y = "bar"; // ERROR as desired
}
,并且你有一个非弱(强?)类型,你有所需的保证:
IComponentOptions.controller
MyController
很高兴接受IControllerWeak
(或let MyComponent = function(): angular.IComponentOptions {
return {
bindings: {},
controller: MyController,
controllerAs: 'vm',
}
}
子类型的构造函数):
{{1}}
这对你有用吗?