admin管理员组

文章数量:1290273

I'm trying to define custom typings for a navigation library using TypeScript, and I haven't wrapped my head around creating a navigate function that takes the Screen's name as a first argument, and the Screen's properties as a second argument while still being type safe.

I'm trying to:

  1. Safely type the screen name (keyof Stack) as a first argument
  2. Safely encapsulate my two navigation stacks (navigate<LoginStack>('HomeScreen') should never work, only the screens from LoginStack should be possible)
  3. Use the correct arguments for the corresponding screen name (keyof Stack) as the second argument

My current approach:

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', {});

While I achieved points 1. and 2., the second parameter (arguments) aren't safely typed as they contain all values from the HomeStackScreens stack:

Whereas I only want to have BaseProps & { isHeadless?: boolean } in this case (See HomeStackScreens definition)

I'm trying to define custom typings for a navigation library using TypeScript, and I haven't wrapped my head around creating a navigate function that takes the Screen's name as a first argument, and the Screen's properties as a second argument while still being type safe.

I'm trying to:

  1. Safely type the screen name (keyof Stack) as a first argument
  2. Safely encapsulate my two navigation stacks (navigate<LoginStack>('HomeScreen') should never work, only the screens from LoginStack should be possible)
  3. Use the correct arguments for the corresponding screen name (keyof Stack) as the second argument

My current approach:

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', {});

While I achieved points 1. and 2., the second parameter (arguments) aren't safely typed as they contain all values from the HomeStackScreens stack:

Whereas I only want to have BaseProps & { isHeadless?: boolean } in this case (See HomeStackScreens definition)

Share Improve this question asked Aug 19, 2020 at 12:50 mrousavymrousavy 1,1171 gold badge9 silver badges34 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

Try this!

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

Example,

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

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

本文标签: javascriptTypeScript type for value of key in objectStack Overflow