在TypeScript中,有两种方法可以声明常量应该符合接口:
interface Foo { x: string; }
const HELLO: Foo = { x: 'hello' };
或
interface Foo { x: string; }
const HELLO = { x: 'hello' } as Foo;
这些似乎具有相同的效果:TypeScript将HELLO
视为具有Foo
类型,并为其指定任何未出现在interface Foo
中的成员都会导致错误。
有没有理由更喜欢一种形式而另一种形式?它们完全相同吗?
答案 0 :(得分:5)
在您的示例中,分配结果相同。但是,在第一个示例中键入变量的功能和对变量进行类型转换的功能与第二个示例中的功能不同。
这是一个扩展示例:
interface Foo { x: string; }
interface Foo2 extends Foo { y: string; }
// typing the variables
const hello: Foo = { x: 'hello' }; // works
const hello2: Foo2 = { x: 'hello', y: 'hello' }; // works
const hello3: Foo2 = { x: 'hello' }; // does not work because property 'y' is missing
// typecasting the variables
const hello4 = hello as Foo2; // works
const hello5 = hello2 as Foo2; // works
const hello6 = { x: 'hello' } as Foo2; // works
// typing the variables
const hello7: Foo = {}; // does not work because property 'x' is missing
const hello8: Foo2 = {}; // does not work because property 'y' is missing
// typecasting the variables
const hello9 = <Foo>{}; // works
const hello10 = <Foo2>{}; //works
// typing must match exact form, where typecasting does not, as long as interface is honored
const hello11: Foo = { x: 'hello', y: 'hello' }; // fails because of extra property 'y'
const hello12 = { x: 'hello', y: 'hello' } as Foo; // works
如您所见,只有在分配的对象具有完全匹配的表单时,键入变量才有效。即使赋值对象无效,也可以对变量进行类型转换,因为它实际上意味着您正在告诉typescript您将确保它在某些时候执行...例如,如果使用无效对象初始化,然后使用某些逻辑集剩下的遗失物。
可以使用as
关键字或使用<type>
添加指定的变量来完成类型转换。
答案 1 :(得分:2)
这适用于Typescript 2.1.4。我不知道其他版本的差异。
在第一个中,如果你这样做,你应该得到一个编译错误:
interface Foo { x: string; }
const HELLO: Foo = { x:'hello', y: 'goodbye' }; // Will not compile.
在第二个中,你基本上将它转换为接口Foo
,因此就编译而言,这是完全有效的。
interface Foo { x: string; }
const HELLO = { x:'hello', y: 'goodbye' } as Foo; // No compilation error.
const yValue = HELLO.y; // compilation error because "y" should not exist according to the interface
const yValue2 = (HELLO as any).y // suddenly works; yValue2 === "goodbye"
前者不允许您使用添加的数据创建对象,因此可以防止愚蠢的错误。后者将允许您转换已创建的对象,该对象具有与接口相同的值。然后,您可以将该对象传递给其他函数或类,就像它是接口一样。它基本上会隐藏其他值。