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

标签 typescript

假设我有一个函数 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/

相关文章:

forms - 如何获取嵌套 formBuilder 组的值

javascript - 在 Angular 6 项目中,@brief 是什么意思?

javascript - 为什么 splice 方法不从数组中删除具有匹配属性值的所有项目?

reactjs - React Developer Tools 将所有组件显示为 "Anonymous"

javascript - 加载页面后如何在Angular 4中获取(DOM)元素的宽度

typescript - TS2339 : Property does not exist on type {}

angularjs - 使用 typescript 缩小编写的 Angular 提供者安全

typescript - 在 eslint 规则中为 JSX.Element 类型的变量指定 PascalCase 命名约定

typescript - 在 TypeORM 和 MySQL 中返回插入查询的 ID

arrays - 使用 ngFor 对从 Firebase 获取的对象进行迭代