这个问题直接类似于TypeScript中的类类型检查
我需要在运行时找出任何类型的变量是否实现了接口。这是我的代码:
interface A{
member:string;
}
var a:any={member:"foobar"};
if(a instanceof A) alert(a.member);
如果您在typescript游乐场中输入这段代码,最后一行将被标记为错误,“名称A不存在于当前作用域”。但事实并非如此,该名称确实存在于当前作用域中。我甚至可以更改变量声明为var a: a ={成员:"foobar"};没有编辑的抱怨。在浏览网页并找到其他问题后,我将接口更改为类,但我不能使用对象字面量来创建实例。
我想知道A类型是如何消失的,但看看生成的javascript就能解释这个问题:
var a = {
member: "foobar"
};
if(a instanceof A) {
alert(a.member);
}
没有将A表示为接口,因此不可能进行运行时类型检查。
我知道javascript作为一种动态语言没有接口的概念。是否有方法对接口进行类型检查?
typescript游乐场的自动完成显示typescript甚至提供了一个方法实现。我怎么使用它?
这里还有另一个选项:模块ts-interface-builder提供了一个构建时工具,可以将TypeScript接口转换为运行时描述符,ts-interface-checker可以检查对象是否满足它。
对于OP的例子,
interface A {
member: string;
}
首先运行ts-interface-builder,它会生成一个带有描述符(比如foo-ti)的新简洁文件。Ts,你可以这样用:
import fooDesc from './foo-ti.ts';
import {createCheckers} from "ts-interface-checker";
const {A} = createCheckers(fooDesc);
A.check({member: "hello"}); // OK
A.check({member: 17}); // Fails with ".member is not a string"
你可以创建一个单行类型保护函数:
function isA(value: any): value is A { return A.test(value); }
你可以在没有instanceof关键字的情况下实现你想要的,因为你现在可以编写自定义类型保护:
interface A {
member: string;
}
function instanceOfA(object: any): object is A {
return 'member' in object;
}
var a: any = {member: "foobar"};
if (instanceOfA(a)) {
alert(a.member);
}
会员众多
如果需要检查大量成员以确定对象是否与您的类型匹配,则可以添加标识符。下面是最基本的示例,并要求您管理自己的鉴别器…您需要深入了解模式,以确保避免重复标识符。
interface A {
discriminator: 'I-AM-A';
member: string;
}
function instanceOfA(object: any): object is A {
return object.discriminator === 'I-AM-A';
}
var a: any = {discriminator: 'I-AM-A', member: "foobar"};
if (instanceOfA(a)) {
alert(a.member);
}
export interface ConfSteps {
group: string;
key: string;
steps: string[];
}
private verify(): void {
const obj = `{
"group": "group",
"key": "key",
"steps": [],
"stepsPlus": []
} `;
if (this.implementsObject<ConfSteps>(obj, ['group', 'key', 'steps'])) {
console.log(`Implements ConfSteps: ${obj}`);
}
}
private objProperties: Array<string> = [];
private implementsObject<T>(obj: any, keys: (keyof T)[]): boolean {
JSON.parse(JSON.stringify(obj), (key, value) => {
this.objProperties.push(key);
});
for (const key of keys) {
if (!this.objProperties.includes(key.toString())) {
return false;
}
}
this.objProperties = null;
return true;
}
你也可以向子组件发送多个输入,其中一个是鉴别器,另一个是实际数据,并检查子组件中的鉴别器,如下所示:
@Input() data?: any;
@Input() discriminator?: string;
ngOnInit(){
if(this.discriminator = 'InterfaceAName'){
//do stuff
}
else if(this.discriminator = 'InterfaceBName'){
//do stuff
}
}
显然,你可以把它移动到任何它适用的地方,比如ngOnChanges函数或setter函数,但这个想法仍然成立。如果你想要一个响应式表单,我还建议尝试将ngModel绑定到输入数据上。你可以使用这些if语句根据传入的数据来设置ngModel,并在html中反映:
<div [(ngModel)]={{dataModel}}>
<div *ngFor="let attr of (data | keyvalue)">
<!--You can use attr.key and attr.value in this situation to display the attributes of your interface, and their associated values from the data -->
</div>
</div>
或者用这个代替:
<div *ngIf = "model == 'InterfaceAName'">
<div>Do This Stuff</div>
</div>
<div *ngIf= "model == 'IntefaceBName'">
<div>Do this instead</div>
</div>
(您可以使用attr。键和attr。值在这种情况下显示接口的属性,以及它们从数据中关联的值)
我知道这个问题已经有了答案,但我认为这可能对试图构建半模糊的角形式的人有用。你也可以将此用于角材料模块(例如对话框),通过数据参数发送两个变量——一个是你的实际数据,另一个是判别器,并通过类似的过程检查它。最终,这将允许您创建一个表单,并围绕流入其中的数据塑造表单。
基于Fenton的回答,下面是我实现的一个函数,用于验证给定对象是否具有接口所具有的键(全部或部分)。
根据您的用例,您可能还需要检查每个接口属性的类型。下面的代码不会这样做。
function implementsTKeys<T>(obj: any, keys: (keyof T)[]): obj is T {
if (!obj || !Array.isArray(keys)) {
return false;
}
const implementKeys = keys.reduce((impl, key) => impl && key in obj, true);
return implementKeys;
}
用法示例:
interface A {
propOfA: string;
methodOfA: Function;
}
let objectA: any = { propOfA: '' };
// Check if objectA partially implements A
let implementsA = implementsTKeys<A>(objectA, ['propOfA']);
console.log(implementsA); // true
objectA.methodOfA = () => true;
// Check if objectA fully implements A
implementsA = implementsTKeys<A>(objectA, ['propOfA', 'methodOfA']);
console.log(implementsA); // true
objectA = {};
// Check again if objectA fully implements A
implementsA = implementsTKeys<A>(objectA, ['propOfA', 'methodOfA']);
console.log(implementsA); // false, as objectA now is an empty object