对象中键值的TypeScript类型

问题描述

我正在尝试使用TypeScript为导航库定义自定义类型,而我并没有全力以赴创建一个navigate函数,该函数以Screen的名称作为第一个参数,而Screen的属性为第二个参数,同时仍保持类型安全。

我正在尝试:

  1. 安全键入屏幕名称keyof Stack)作为第一个参数
  2. 安全地封装我的两个导航堆栈(navigate<LoginStack>('HomeScreen')永远不会起作用,只能显示LoginStack中的屏幕)
  3. 为相应的屏幕名称keyof Stack)使用正确的参数作为第二个参数

我目前的做法:

ScreenDeFinitions.ts

export interface LoginStackScreens {
    LoginScreen: BaseProps & { isHeadless?: boolean };
    ForgotPasswordScreen: BaseProps & { email: string };
}
export interface HomeStackScreens {
    HomeScreen: BaseProps & { isHeadless?: boolean };
    SavedScreen: BaseProps;
    ChatsListScreen: BaseProps;
    MyProfileScreen: BaseProps;
    PostDetailsScreen: BaseProps & {
        post: Post;
    };
    // ... some more
}

Navigation.ts

type ValueOf<T> = T[keyof T];
function navigate<Stack extends HomeStackScreens | LoginStackScreens>(screenName: keyof Stack,props: ValueOf<Stack>): void {
    // Navigation logic
}

navigate<HomeStackScreens>('HomeScreen',{});

虽然我获得了 1。 2。分,但第二个参数(自变量)包含所有值,因此无法安全输入来自HomeStackScreens堆栈:

Screenshot of VSCode showing all types of arguments

在这种情况下,我只想拥有BaseProps & { isHeadless?: boolean }(请参见HomeStackScreens定义)

解决方法

尝试一下!

function navigate<Stack extends {}>(
  screenName: keyof Stack,props: Stack[typeof screenName]
) {
  // Implementation
}

示例

type SomeStack = {
  someScreen: {
    test: string
  }
}

navigate<SomeStack>('someScreen',{
  test: 5 // Fails - should be a string!
})