假设我有一个函数 changeType
,它接受 Foo
并将其转换为 Bar
。
interface Foo {
num: number;
}
interface Bar {
str: string;
}
function changeType(foo: Foo): void {
(foo as any).str = foo.num.toString();
delete (foo as any).num;
}
let foobar: Foo | Bar = { num: 1 };
changeType(foobar);
有什么方法可以告诉 TypeScript 编译器运行 changeType
必然会将传入的参数更改为不同的类型吗?我想也许有类似的东西:
function changeType(foo: Foo): foo as Bar { /*...*/ }
然后该函数必须返回foo
而不是不返回任何内容。更好的是一些奇怪的语法,例如 function(...): void, foo => Bar { ... }
。
我知道这是一个非常奇怪的情况,但它是处理 Object.freeze
的一部分——在讨论如何实现它时似乎被忽略的部分。通常the conversation重点关注返回值,而不是已修改的传递值本身。
另一个案例与继承有关。假设您有一个三角形
和一个平行四边形
,它们都继承自Shape
。
type Point = [number, number];
interface Shape {
name: 'triangle' | 'square';
points: Point[];
}
interface Triangle extends Shape {
name: 'triangle';
points: [Point, Point, Point];
}
interface Parallelogram extends Shape {
name: 'parallelogram';
points: [Point, Point, Point, Point];
}
现在您想要将三角形
转变为一个平行四边形
,而不是创建一个新的Shape
对象。
function makeParallelogram(triangle: Triangle): void;
function makeParallelogram(shape: Shape): void {
Object.assign(shape, {
name: 'parallelogram',
points: (shape as Triangle).points.push(calcFourthPoint(shape as Triangle);
});
}
function calcFourthPoint(triangle: Triangle): Point {
/* some geometry here */
}
最佳答案
TypeScript 无法完全满足您的需求。这个issue来自 GitHub 的内容非常接近你想要的。 TypeScript 无法深入分析代码的控制流,因此很难从函数的功能推断出正确的类型。
但是如果使用 return 语句、重载和 type guards 也可以达到同样的效果。 .
function isFoo(f: Foo | Bar): f is Foo {
return (f as Foo).num !== undefined;
}
function changeType(foo: Foo): Bar
function changeType(foo: Bar): Foo
function changeType(foo: Foo | Bar): Foo | Bar {
if (isFoo(foo)) {
// Convertion logic can be anything. But I suggest not to mutate original object but create new one and fill it with props.
let res: Bar = { str: foo.num.toString() }
return res;
}
else {
let res: Foo = { num: +foo.str }
return res;
}
}
以及用法
let foobar: Foo | Bar = { num: 1 }; // Type is Foo
let r: Bar = changeType(foobar); // Return is Bar
关于typescript - 更改 TypeScript void 函数中传递对象的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56926309/