typescript-modulförstärkning med härledd typ


Jag hoppas att någon kan hjälpa mig med detta. Jag skapar ett designsystem och har därför 2 repos: react-komponentbiblioteket och applikationen som använder det. I react-biblioteket exporterar jag en createTheme-funktion som applikationen kan använda för att skapa sitt tema:

// library
export const createTheme(options) => { ... }
// application
import {createTheme} from 'library';
export const theme = createTheme( ... );

Komponentens props är typade genom att använda en DefaultTheme-typ i biblioteket. Detta gör det möjligt för användarna av biblioteket att definiera några varianter eller storlekar i ett globalt tema. till exempel:

export type ComponentProps = {
    // looks like this in the DefaultTheme: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl"
    size?: keyof DefaultTheme['components']['SomeComp']['props']['size'];
};

export const SomeComp = () => {
    const theme = useTheme();
    const className = doSomethingWithContext(theme);
    return (<div className={className}>something</div>)
}

Nu vill jag kunna ställa in de korrekta typerna i applikationen genom att använda modulaugumentering i TypeScript för DefaultTheme-typen:

import 'library';

declare module 'library' {
    export interface DefaultTheme {
        components: {
            SomeComp: {
                props: {
                    size: {
                        small: 'small';
                        medium: 'medium';
                        large: 'large';
                    };
                };
            };
        };
    }
}

Detta fungerar utan problem! Men jag vill använda typen av returvärdet från createTheme-funktionen, så jag inte behöver skriva det två gånger. Detta är vad jag vill:

import 'library';
import {CustomApplicationTheme} from './theme';

declare module 'library' {
    export interface DefaultTheme extends CustomApplicationTheme {}
}

När jag gör detta visas inga fel, men typen av size-egenskapen på SomeComp faller alltid tillbaka på bibliotekets DefaultTheme:

// size should be of the type: 'small' | 'medium' | 'large'
// but ts says it should be of type: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl"
// so i get a type error for the size property
<SomeComp as="h1" size="small">Hello world</SomeComp>

1. Varför kan jag inte använda en härledd typ för modulförstärkning?

Jag försökte också använda en typ istället för ett gränssnitt för module augmentation, men då får jag följande felmeddelande:

import 'library';
import { theme } from './theme';

declare module 'library' {
    // Duplicate identifier 'DefaultTheme'.ts(2300)
    // default-theme.d.ts(48, 21): 'DefaultTheme' was also declared here
    export type DefaultTheme = typeof theme;
}

Faktiskt skulle jag föredra att använda en typ istället för ett gränssnitt. Jag skulle vara mycket glad över hjälp. Tack.