最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - TypeScript autocomplete for user defined variants tokens in React Native library - Stack Overflow

programmeradmin3浏览0评论

I am developing a React Native library that includes a Button component and a TokenManager class for managing theme-related tokens. The flow I am aiming for is as follows:

  1. In the app (App.tsx), the user defines their own token values (e.g., button variants).
  2. These tokens are then passed into the TokenManager class in the library to manage and store the values.
  3. Finally, in the Button component (Button.tsx in the library), I need to access these tokens, particularly the variants, and have TypeScript provide type suggestions for them when the Button is used in the app.

The main challenge is getting TypeScript to recognize the correct types for the tokens, especially for the variants (such as 'primary', 'secondary', 'tertiary'), and applying these types to the colorScheme prop in the Button component.

The issue:

I can't directly import the tokens from the app into the Button component, but I still need to ensure that TypeScript can correctly infer the types of the tokens in the component. Specifically, I want the colorScheme prop of the Button component to receive type suggestions for the available variants.

How can I correctly type the tokens in such a way that they are accessible in the Button.tsx component, and that TypeScript offers autocomplete and proper type checking when using them in the app?

Here’s the current code structure:

In App.tsx (user app):

// define tokens
const buttonTokens = {
  variants: ['primary', 'secondary', 'tertiary'] as const, // Use 'as const' to preserve literal types
  text: 'Press me',
  onPress: () => console.log('Button pressed'),
  colorScheme: 'primary', // 'primary' is valid because it's part of variants
} as const;

// set the tokens
TokenStore.init(buttonTokens);

In TokenManager.ts (library):

export class TokenStore<T extends string> {
    private static instance: TokenStore<any> | null = null;
    private tokens!: Tokens<T>;

    private constructor(tokens: Tokens<T>) {
    this.tokens = tokens;
    }

    static init<const T extends readonly string[]>(tokens: Tokens<T[number]>) {
        if (!TokenStore.instance) {
            TokenStore.instance = new TokenStore<T[number]>(tokens);
        } 
    }

    static getInstance<T extends string>(): TokenStore<T> {
        if (!TokenStore.instance) {
            throw new Error('TokenStore has not been initialized.');
        }
        return TokenStore.instance as TokenStore<T>;
    }

    getTokens(): Tokens<T> {
        return this.tokens;
    }
}

In Button.tsx (library):

const tokens = TokenStore.getTokens();
// Button component code...

Tokens type is: Tokens<string> But I expected to be: Tokens<"primary" | "secondary" | "tertiary">

The goal is to be able to do this in any file of the app:

<Button
        variants={tokens.variants}
        text="Press me"
        onPress={() => console.log('Button pressed')}
        colorScheme="tertiary" // get suggestions from ts: "primary, secondary, tertiary"
      />

So those variants ("primary", "secondary", "tertiary") depends of what user define in the tokens.

My current understanding and doubts:

I'm relatively new to TypeScript and am not sure if this is the correct approach. Are there any other strategies or workarounds I should try to achieve this? I would appreciate advice on whether this is the right direction or if there's a more effective way to handle it.

Thanks in advance to any advice.

发布评论

评论列表(0)

  1. 暂无评论