Сопоставленные типы в аргументах функции - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть список экранов в файле:

file1.ts

export const LANDING = 'landing.Landing'
export const REGISTER = 'landing.Register'
export const LOGIN = 'landing.Login'

и список реквизитов для каждого экрана в другом файле

file2.ts


type LandingProps = { foo: string }
type RegisterProps = { bar: number }
type LoginProps = { baz: object }

Я хочу создать функцию navigate в другом файле, например:

file3.ts

import { LANDING, REGISTER, LOGIN } from 'file1'
import { LandingProps, RegisterProps, LoginProps } from 'file2'

const screens = [LANDING, REGISTER, LOGIN] as const
type ScreenType = typeof screens[number]

type Props = LandingProps | RegisterProps | LoginProps

function navigate(screen: ScreenType, props: Props) {
    console.log('Navigation to screen ', screen)
    console.log('Props are: ', props)
}

Как мне ввести аргумент props, чтобы реквизиты соответствовали соответствующему типу экрана?

И, на заметку, возможно ли создать тип на основе всего экспорта из file1 без указания какого?

1 Ответ

1 голос
/ 22 апреля 2020

Чтобы компилятор ограничивал тип props в зависимости от типа screen, вам нужно дать ему отображение. Самый простой способ сделать это в вашем случае - создать фиктивный интерфейс, поскольку типы props уже являются клавишными:

interface ScreenPropsMapping {
  [LANDING]: LandingProps,
  [REGISTER]: RegisterProps,
  [LOGIN]: LoginProps
}

Поскольку LANDING et c равны const строковые литералы, мы можем использовать их как вычисляемые ключи в интерфейсах.

Затем вы даете navigate() a generi c подпись, подобную этой:

function navigate<K extends keyof ScreenPropsMapping>(
  screen: K, props: ScreenPropsMapping[K]
) {


}

Здесь K должен быть одним из ключей интерфейса отображения, а props - конкретным типом свойства для этого ключа:

navigate(LANDING, { foo: "" }); // okay
navigate(LANDING, { bar: 1 }); // error

Что касается вашего примечания, если вы действительно хотите, чтобы тип был объединением всех типов экспортируемых значений в модуле, вы можете сделать что-то вроде этого:

import * as File1 from 'file1'
type File1Types = typeof File1[keyof typeof File1];
// type File1Types = "landing.Landing" | "landing.Register" | "landing.Login"

Хорошо, надеюсь что помогает; удачи!

Детская площадка ссылка на код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...