Return return-type of interface property based on a key as an argument

Issue

I struggle with Typescript once again.
My goal is to create a function for my e2e tests, which goes to a specific page in my app, reloads it and then returns the page-object of the specified page.

However it does not correctly determine the returned value. Right now, Typescript does not like that the createTracksPage() returns an object with less properties than the createTracksPage()

Furthermore, is there a more elegant way to solve this problem?

Here is a link to the playground

const routes = {
  tracks: "tracks",
  settings: "settings",
} as const

type IRoutes = keyof typeof routes


async function resetTo<T extends IRoutes>(
  location: T,
): Promise<
  {
    tracks: ReturnType<typeof createTracksPage>
    settings: ReturnType<typeof createSettingsPage>
  }[T]
> {
  // Do side effects..

  if (location === "settings") return createSettingsPage()
  if (location === "tracks") return createTracksPage()

  throw new Error("location is not implemented") // For some reason this does not get treated as "never" code
}



// Create page object functions

function createTracksPage() {
  return { 
    a: "a", b: "b" 
    }
}

function createSettingsPage() {
  return { 
    a: "a", b: "b" , c: "c" //! Has more properties than tracks return value and TS does not like it
    }
}

Solution

Would it be good enough to add overloads like this?

async function resetTo(location: "tracks"): Promise<ReturnType<typeof createTracksPage>>
async function resetTo(location: "settings"): Promise<ReturnType<typeof createSettingsPage>>
async function resetTo<T extends IRoutes>(
  location: T,
): Promise<
  ReturnType<typeof createTracksPage> | ReturnType<typeof createSettingsPage>
  > {
...
}

(I’d make it a comment, but the link is too long.)

Answered By – Alexey Romanov

Answer Checked By – Mildred Charles (AngularFixing Admin)

Leave a Reply

Your email address will not be published.