Yes I've seen a lot of question like Typescript return type depending on parameter
But my problem is a little different: the parameter type is not JS/TS basic type, it's the class type. In that class-type case, the solution in the question mentioned above can not work.
class Foo {}
class Bar {}
// my attempts
// 1.
function update<T extends Foo | Bar>(item: T): T extends Foo ? 'Foo' : 'Bar' {
return {} as any
}
// 2.
function update(item: Foo): 'Foo'
function update(item: Bar): 'Bar'
function update(item: Foo | Bar): 'Foo' | 'Bar' {
return {} as any
}
// testing
const foo = new Foo()
const bar = new Bar()
const result1 = update(foo) // typeof result1: "Foo"
const result2 = update(bar) // typeof result2: "Foo", expected "Bar" however
As the code above show, I want get return type of the function update()
according to the parameter type which could be either class Foo
type or class Bar
type, but it just not work, I couldn't figure it. Please help me.
CodePudding user response:
Your approach to overloads is sounds. The only issue is that the classes as structurally equivalent and thus will be equivalent in the type system (therefore it appears the wrong overload will be selected)
If the classes have some fields, you will get the expected behavior. Private fields are the best way to ensure no aliasing of classes can occur, private fields essentially make the classes behave nominally:
class Foo { #foo = true }
class Bar { #bar = true}
function update(item: Foo): 'Foo'
function update(item: Bar): 'Bar'
function update(item: Foo | Bar): 'Foo' | 'Bar' {
return {} as any
}
// testing
const foo = new Foo()
const bar = new Bar()
const result1 = update(foo) // typeof result1: "Foo"
const result2 = update(bar) // typeof result2: "Bar"