Suppose I have a function changeType that takes in a Foo and converts it into a 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);
Is there any way to tell the TypeScript compiler that running changeType will necessarily change the passed in argument to a different type? I thought maybe there might be something like:
function changeType(foo: Foo): foo as Bar { /*...*/ }
and then the function would have to return foo rather than not returning anything. Even better would be some strange syntax like function(...): void, foo => Bar { ... }.
I know this is a very strange case, but it is part of handling Object.freeze--the part that seems to go ignored when discussing how to implement it. Typically the conversation focuses on the returned value, and not the passed value itself, which is modified.
Another case revolves around inheritance. Suppose you have a Triangle and a Parallelogram that both inherit from 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];
}
Now you want to mutate the Triangle into a Parallelogram, rather than creating a new Shape object.
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 */
}
Object.freezecase is legit, though.