javascript - TypeScript-typ för värdet av en nyckel i ett objekt


Jag försöker definiera egna typer för ett navigeringsbibliotek med TypeScript, och jag har inte riktigt förstått hur man skapar en navigate-funktion som tar skärmens namn som första argument och skärmens egenskaper som andra argument samtidigt som det fortfarande är typsäkert.

Jag försöker:

  1. Skriv säkert skärmnamnet (keyof Stack) som ett första argument
  2. Kapsla säkert in mina två navigeringsstackar (navigate<LoginStack>('HomeScreen') bör aldrig fungera, endast skärmarna från LoginStack bör vara möjliga)
  3. Använd de korrekta argumenten för motsvarande skärmnamn (keyof Stack) som det andra argumentet

Min nuvarande metod:

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

Medan jag uppnådde punkterna 1. och 2., är den andra parametern (argumenten) inte säkert typad eftersom de innehåller alla värden från HomeStackScreens-stacken:

Medan jag bara vill ha BaseProps & { isHeadless?: boolean } i det här fallet (Se HomeStackScreens-definitionen)

Svar #1

Prova detta!

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

Exempel,

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

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

Relaterade artiklar