1 year ago

#87275

test-img

jarvispact

typescript module augmentation with inferred type

i hope someone can help me with this. I am creating a design system and therefor have 2 repos: the react component library and the application that consumes it. In the react library i am exporting a createTheme function which the application can use to create its theme:

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

The component props are typed by using a DefaultTheme type in the library. This allows the cnsumers of the library to define some variants or sizes in a global theme. for example:

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>)
}

Now i want to be able to setup the correct types in the application by using module augmentation in typescript for the DefaultTheme type:

import 'library';

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

This works without any problem! But i want to use the type of the return value of the createTheme function, so i dont have to write it twice. This is want i want:

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

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

When i do this, it shows no errors but the type of the size prop of SomeComp always falls back to the DefaultTheme of the library:

// 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. Why do i cannot use a inferred type for module augmentation?

Also i tried to use a type instead of an interface for module augmentation, but then i get the following error message:

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;
}

Actually i would prefer using a type instead of an interface. I would be very happy about help. Thank you.

typescript

module-augmentation

0 Answers

Your Answer

Accepted video resources