Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing an object's type after calling a particular function

Tags:

typescript

In the code below can one tell the compiler that after calling flip(), becomeFoo will change from type Bar to type Foo?

type Bar = {
    type: 'bar'
    flip: ()=>void
}
type Foo = {
    type: 'foo'
    flip: ()=>void
}

let becomeFoo:Bar = {
    type: 'bar',
    flip: ()=> { (becomeFoo as unknown as Foo).type = 'foo' }
}

becomeFoo.flip() : becomeFoo is Foo

code

This seems like a similar requirement to using type predicates ala function isFish(pet: Fish | Bird): pet is Fish

Probably a silly question as I assume the answer is no, but one doesn't know what one doesn't know.

like image 758
TrevTheDev Avatar asked Dec 07 '25 07:12

TrevTheDev


1 Answers

This gets you part of the way to where it appears you want to go.

We can (as @T.J. Crowder suggests) return a value from flip that contains type information, even without creating a new object. This type information, along with an assignment back to the variable, can be enough to reassign the static type of the variable after a call to flip():

type Bar = {
    type: 'bar'
    flip: ()=>Foo
}
type Foo = {
    type: 'foo'
    flip: ()=>Bar
    canNowDoThis: () => void
}

let becomeFoo:Foo | Bar = {
    type: 'bar',
    flip: function() { (becomeFoo as unknown as Foo).type = 'foo'; return this as unknown as Foo; }
}

// invoking this makes the type Foo
becomeFoo = becomeFoo.flip()

// Now we can use Foo-specific properties
becomeFoo.canNowDoThis()

// no cast needed
let nowFoo: Foo = becomeFoo

Playground

like image 84
David P. Caldwell Avatar answered Dec 09 '25 17:12

David P. Caldwell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!