这是我的代码,我知道这有点长,但并不难理解。 它在最后一行显示错误,并且在那里也失去了智能感知能力。 “类型'Test | Test2'上不存在属性'test'。” 如您所见,“ test”属性显然在“ Test”类中。那怎么了?
class Test{
test: string = 'test';
}
class Test2{
test2: string = 'test2';
}
function isTest(obj: Test|Test2): obj is Test{
if(obj instanceof Test)
return true;
else
return false;
}
function test(obj: Test|Test2): Test|Test2{
if(isTest(obj))
return obj as Test;
else
return obj as Test2;
}
let varTest: Test = new Test();
console.log(test(varTest).test); //this line is broken
答案 0 :(得分:1)
test()
的返回类型是静态的,这意味着它的返回值将始终始终为Test | Test2
,无论其调用方式如何。这意味着varTest
可以是Test
或Test2
(不包含test
属性),因此错误是正确地让您知道您要尝试的属性访问可能不存在。
如果需要动态返回类型,则需要根据问题转向泛型,重载或条件类型。在您的情况下,我们可以使用函数重载。
Function overloads允许您指定以输入类型为条件的返回类型。为了使您的test()
函数按预期工作,我们用两个条件对其进行重载:一个条件用于Test
,另一个条件用于Test2
:
function test(obj: Test): Test; // given Test, return Test
function test(obj: Test2): Test2; // given Test2, return Test2
function test(obj: Test | Test2): Test | Test2{
if(isTest(obj))
return obj as Test;
else
return obj as Test2;
}
let varTest: Test = new Test();
console.log(test(varTest).test); // OK
let varTest2: Test2 = new Test2();
console.log(test(varTest2).test); // Error! 'test' does not exist in Test2
请参见playground link。
答案 1 :(得分:0)
@Dakito,这种打字稿Union类型非常棘手。
但是,如果您在这里看一下:Typescript Union Types,您会发现您将不得不添加检查以确保您可以安全地从对象访问字段或方法,而不会假定它不会失败。
// this line is broken
let varTest: Test = new Test();
let testResult: Test | Test2 = test(varTest);
// Adding these checks here will help you safely access the correct values.
// You can also improve this code by using User-Defined Type Guards
if(<Test>testResult.test) {
console.log((<Test>testResult).test);
} else if(<Test2>testResult.test2) {
console.log((<Test2>testResult).test2);
}