gpt4 book ai didi

typescript - 在 TypeScript void 函数中更改传递对象的类型

转载 作者:搜寻专家 更新时间:2023-10-30 21:32:43 24 4
gpt4 key购买 nike

假设我有一个函数 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关注返回的值,而不是修改过的传递值本身。

另一个案例围绕着继承。假设您有一个 Triangle 和一个 Parallelogram,它们都继承自 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];
}

现在您想将 Triangle 变成 Parallelogram,而不是创建一个新的 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com