Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular Typescript Reflect.getMetadata设计:类型返回对象,而不是没有角度测试台的日期_Angular_Typescript_Reflection_Reflect Metadata - Fatal编程技术网

Angular Typescript Reflect.getMetadata设计:类型返回对象,而不是没有角度测试台的日期

Angular Typescript Reflect.getMetadata设计:类型返回对象,而不是没有角度测试台的日期,angular,typescript,reflection,reflect-metadata,Angular,Typescript,Reflection,Reflect Metadata,首先,我想说,它不是的复制品,而是相似的 以下代码: import {} from 'reflect-metadata'; import 'core-js/es7/reflect'; function test(target: any, key: string) { console.log(key, Reflect.getMetadata('design:type', target, key).name); } class Class { } class Test { @t

首先,我想说,它不是的复制品,而是相似的

以下代码:

import {} from 'reflect-metadata';
import 'core-js/es7/reflect';

function test(target: any, key: string) {
    console.log(key, Reflect.getMetadata('design:type', target, key).name);
}

class Class { }

class Test {
    @test item: String;
    @test date: Date;
    @test instance: Class;
}
如果使用
ts摩卡测试运行。ts
输出

item Object
date Object
instance Class
而如果使用作为angular2项目输出一部分设置的
karma start
运行

item String
date Date
instance Class
为什么会这样?如何使测试结果一致


(karma配置是从angular2项目中提取的,没有清理)

我可以修复一个bug,但我不知道如何修复另一个bug,因为我找不到这种类型的基元类型。因为类型只存在于typescript中,在javascript中没有类型。字符串的类型不是对javascript字符串类的引用,如果你想让typescript正确编译,你必须在输入端使用
string
。比如
foo:string
或者
foo:string
;当你写
时,让string:string=string
编译器报告错误,因为左侧引用类型,右侧引用字符串构造函数,它们是不同的。对不起,我的英语不好,所以我希望你能理解我说的话。难以想象,typescript编译器会将字符串类型编译成String类,然后编译成.js文件,您可以使用
tsc
编译js文件并查看结果。可以运行第三个测试,我认为用户定义的类扮演着两个角色:
类的实例
&
类的类型
。但是
日期
&
字符串
类型
/
构造函数
分为两部分:
类型
作为接口“字符串”,
constructor函数
通过全局变量
StringConstructor

import 'reflect-metadata';
import 'core-js/es7/reflect';

function Test(expectedType: any) {
    return function (target: any, key: string): void {
        let type = Reflect.getOwnMetadata('design:type', target, key);
        test(`${target.constructor.name} ${key}'s type should be ${expectedType.name} but was ${type.name}!`, () => {
            expect(type).toBe(expectedType);
        });
    }
}

class TestClass {
}

class ReflectMetadataTest {
    @Test(String) item: string;
    @Test(Date) date: Date;
    @Test(TestClass) instance: TestClass;
}


test('metadata', () => {
    let type = String;
    let clazz = ReflectMetadataTest.prototype;
    let decorator: any = Reflect.metadata("foo", type);
    decorator(clazz, 'item', void 0);

    expect(Reflect.getMetadata('foo', clazz, 'item')).toBe(type);
});
也许下面的两个测试可以回答你的问题
Date
&
String
是遗留系统。它们通过函数或类声明定义类,因此typescript无法获取类型信息。然后,如果在内存中运行typescript,typescript将传递
对象
类型,但是,当
tsc
将.ts编译为.js时,它将
类型
保留为与
构造函数函数
相同。下面的测试是假设函数
Foo
是基于函数的类,类型脚本无法推断
Foo
类型,因此它会发出一个
对象
来反映.metadata(),但当您通过
tsc
将测试文件编译到.js中时,编译器将保留
类型
构造函数

import 'reflect-metadata';
import 'core-js/es7/reflect';

function Test(expectedType: any) {
    return function (target: any, key: string): void {
        let type = Reflect.getOwnMetadata('design:type', target, key);
        test(`${target.constructor.name} ${key}'s type should be ${expectedType.name} but was ${type.name}!`, () => {
            expect(type).toBe(expectedType);
        });
    }
}


function Foo() {

}
interface Foo {
}


class ReflectMetadataTest {
    @Test(Foo/*ref function*/) foo: Foo/*ref interface*/;
}

test('metadata', () => {
    let type = Foo;
    let clazz = ReflectMetadataTest.prototype;
    let decorator: any = Reflect.metadata("foo", type);
    decorator(clazz, 'item', void 0);

    expect(Reflect.getMetadata('foo', clazz, 'item')).toBe(type);
});
总结 如果要使元数据在.js和.ts中都能正确工作,则必须使用
基于旧函数的类定义
包装类
/
子类

import 'reflect-metadata';
import 'core-js/es7/reflect';

function Test(expectedType: any, same: boolean) {
    return function (target: any, key: string): void {
        let declaredType = Reflect.getOwnMetadata('design:type', target, key);

        test(`${target.constructor.name} ${key}'s type should ${same ? '' : 'not '}be \`${expectedType.name}\` & declared type was \`${declaredType.name}\`!`, () => {
            expect(declaredType == expectedType).toBe(same);
        });
    }
}


function Foo() {

}
interface Foo {
}
class MyDate extends Date{

}
class ReflectMetadataTest {
    // this test always false even if you compile .ts it into .js file
    @Test(Foo/*ref function*/, false) foo: Foo/*ref interface*/;

    //this test is true when you compile .ts it into .js file
    @Test(Date, false) date: Date;
    @Test(String, false) String: String;
    @Test(Number, false) Number: Number;

    //this test is always true both in .ts & .js
    @Test(Number, true) number: number;
    @Test(Boolean, true) boolean: boolean;
    @Test(String, true) string: string;
    @Test(MyDate, true) myDate: MyDate;
    @Test(ReflectMetadataTest, true) test: ReflectMetadataTest;
}

这部分解释了为什么它不应该在内置类型上工作,以及如何解决字符串问题。这并不能解释为什么我使用karma+phantomjs在angular2测试台上运行测试时正确识别日期…日期<代码>也是同样的问题。因为typescript无法在内存中描述日期类型,所以它将<代码>对象<代码>传递给装饰器,也不会将日期<代码>传递给装饰器,这可能是typescript的一个缺陷?但是用户定义的类结合了两个部分
type
class
,因此编译器可以在内存中正确地传递它。好的,那么你是说在karma/phantomjs中,日期传递给装饰器而不是对象,因为类在某个地方被重新定义了?我的问题是,当我使用karma/phantomjs时,它为什么会起作用?因为
ts mocha
没有编译成js,它直接在内存中运行测试。另一个编译成.js可能是通过
webpack
/
babel
。我想我可以回答你的问题,
Date
&
String
是遗留系统。它们通过函数或类声明定义类,因此typescript无法获取类型信息。然后,如果在内存中运行typescript,typescript将传递
对象
类型,但是,当
tsc
将.ts编译为.js时,它保留
类型
,与
构造函数一样。