admin管理员组

文章数量:1123778

I'm defining some overloads for a typescript function

export function createRoute<
  const TOptions,
  const TComponent extends Component
>(options: TOptions & CreateRouteOptions & WithComponent<TComponent, TOptions>): Route<TOptions> { ... }

CreateRouteOptions is a simple type that defines expected properties of a route

export type CreateRouteOptions = {
  name: string,
  path: string,
  query: string,
}

WithComponent is slightly more complicated, but basically just includes some context around adding a component and optional props callback

export type WithComponent<
  TComponent extends Component = Component,
  TOptions = unknown
> = {
  component: TComponent,
  props?: (route: TOptions) => ComponentProps<TComponent>,
}

createRoute only takes a single argument that is an object. TOptions really should match CreateRouteOptions but I found that putting const TOptions extends CreateRouteOptions in the generics broke my WithComponents type. Most of this is working how I want, except the route argument of the props callback is unknown. I'm struggling to understand how Typescript is building the TOptions type.

Example

const myRoute = createRoute({
  name: 'foo',
  path: '/',
  query: '',
  component: SomeComponent,
  props: (route) => { ... }
  //        ^? EXPECTED { name: 'foo', path: '/', query: '' } RECIEVED unknown
})

Typescript Playground

Playground Example

type Component = { template: string, script: string, props: Record<string, any> }
type ComponentProps<T> = T extends { props: infer TProps extends Record<string, any> } ? TProps : {}
const SomeComponent = {
    template: 'something',
    script: '',
    props: {
        foo: true,
        bar: 123
    }
} satisfies Component

type Route<T> = T & {id: number}

type CreateRouteOptions = {
  name: string,
  path: string,
  query: string,
}

export type WithComponent<
  TComponent,
  TOptions
> = {
  component: TComponent,
  props?: (route: TOptions) => ComponentProps<TComponent>,
}

function createRoute<
  const TOptions,
  const TComponent
>(options: TOptions & CreateRouteOptions & WithComponent<TComponent, TOptions>): Route<TOptions> {
    throw 'not implemented'
}

const myRoute = createRoute({
  name: 'foo',
  path: '/',
  query: '',
  component: SomeComponent,
  props: (route) => ({ foo: true, bar: 14 })
  //        ^? EXPECTED { name: 'foo', path: '/', query: '' } RECIEVED unknown
})

I'm defining some overloads for a typescript function

export function createRoute<
  const TOptions,
  const TComponent extends Component
>(options: TOptions & CreateRouteOptions & WithComponent<TComponent, TOptions>): Route<TOptions> { ... }

CreateRouteOptions is a simple type that defines expected properties of a route

export type CreateRouteOptions = {
  name: string,
  path: string,
  query: string,
}

WithComponent is slightly more complicated, but basically just includes some context around adding a component and optional props callback

export type WithComponent<
  TComponent extends Component = Component,
  TOptions = unknown
> = {
  component: TComponent,
  props?: (route: TOptions) => ComponentProps<TComponent>,
}

createRoute only takes a single argument that is an object. TOptions really should match CreateRouteOptions but I found that putting const TOptions extends CreateRouteOptions in the generics broke my WithComponents type. Most of this is working how I want, except the route argument of the props callback is unknown. I'm struggling to understand how Typescript is building the TOptions type.

Example

const myRoute = createRoute({
  name: 'foo',
  path: '/',
  query: '',
  component: SomeComponent,
  props: (route) => { ... }
  //        ^? EXPECTED { name: 'foo', path: '/', query: '' } RECIEVED unknown
})

Typescript Playground

Playground Example

type Component = { template: string, script: string, props: Record<string, any> }
type ComponentProps<T> = T extends { props: infer TProps extends Record<string, any> } ? TProps : {}
const SomeComponent = {
    template: 'something',
    script: '',
    props: {
        foo: true,
        bar: 123
    }
} satisfies Component

type Route<T> = T & {id: number}

type CreateRouteOptions = {
  name: string,
  path: string,
  query: string,
}

export type WithComponent<
  TComponent,
  TOptions
> = {
  component: TComponent,
  props?: (route: TOptions) => ComponentProps<TComponent>,
}

function createRoute<
  const TOptions,
  const TComponent
>(options: TOptions & CreateRouteOptions & WithComponent<TComponent, TOptions>): Route<TOptions> {
    throw 'not implemented'
}

const myRoute = createRoute({
  name: 'foo',
  path: '/',
  query: '',
  component: SomeComponent,
  props: (route) => ({ foo: true, bar: 14 })
  //        ^? EXPECTED { name: 'foo', path: '/', query: '' } RECIEVED unknown
})
Share Improve this question edited yesterday stackoverfloweth asked yesterday stackoverflowethstackoverfloweth 6,9055 gold badges41 silver badges75 bronze badges 5