create-react-library icon indicating copy to clipboard operation
create-react-library copied to clipboard

correct way to define types?

Open saurabhnemade opened this issue 5 years ago • 6 comments

If we try typescript boilerplate then got following error:

I have dir structure as following:

components
     Button
          index.tsx
          types.d.ts

types.d.ts

declare interface ButtonProps {
   name?: string
}

declare type ButtonPropsType  = ButtonProps;

index.tsx

import * as React from 'react';
import {ButtonPropsType} from './types': // not sure why we need to import it. it should be auto resolvable. May be you can point me in right direction on how to auto resolve types

export default function (props: ButtonPropsType) {
    return (
        <div>Simple button</div>
    );
};

The behaviour I see from this is the target generated type in dist has following definition :

/// <reference types="react" />
import { ButtonPropsType } from './types';
export default function (props: ButtonPropsType): JSX.Element;

but the definition of ButtonPropsType is not included in dist.

Can you please let us know how to correctly use it within this boilerplate?

In simple language, imported types are not emitted in dist. Not sure if I am doing something wrong here.

saurabhnemade avatar Jul 07 '20 23:07 saurabhnemade

Turns out typescript skips .d.ts. Here is good explanation on same: https://stackoverflow.com/questions/56018167/typescript-does-not-copy-d-ts-files-to-build

Since we are supporting typescript, can we introduce this copy-dts into create-react-library itself?

Seems like a pretty good feature for typescript boilerplate.

saurabhnemade avatar Jul 09 '20 11:07 saurabhnemade

if you include your interface inside of your typescript instead of using declarations files you won't have to import them (unless you put them in a different file) and you won't have to include them. Your IDE will get the types from the imports.

import * as React from 'react';

 interface ButtonProps {
   name?: string
}

export default function (props: ButtonProps ) {
    return (
        <div>Simple button</div>
    );
};

RickeyWard avatar Sep 24 '20 23:09 RickeyWard

Yes. That works but isn't it a good practice to keep d.ts files separate? The basic purpose of separating the type definitions is to allow readability, remove cyclic dependencies and avoid big file sizes. If we keep adding types to same file as react component, it becomes a chaos. It can neither be readable as a typescript code nor react code.

If you see libraries which started as JS and then later they added typescript definitions they also follow the same pattern to keep definitions in separate files.

I am not sure which is correct approach to follow but from my personal experience being developer on both javascript and typescript and having developed multiple enterprise libraries, I can certainly say that multiple people follow multiple approaches to using both js and ts. Restricting to just one way is limiting the functionality and potential loss of interest for users who want to use different approach!!

saurabhnemade avatar Oct 04 '20 22:10 saurabhnemade

I think you're mixing up ideas. Type declarations files (d.ts) only exists for getting types against non-typescript code (or for transpiled code to maintain the types associated). When you write typescript the compiler generates the types definitions files for the compiled javascript output. No one manually maintains type declarations files intentionally. Hand written declaration files primarily exist for projects not written in typescript that you want types for.

if you mean keeping interfaces in a separate file, that is a case of taste. But typically if the interface is for proptypes they are always in the same file as they are a married pair and depend on each other. Also its as for "big file sizes" that is up to taste. related code lives together, you do you.

When you use "declare" you are saying "there already exists a thing with a type such that" as opposed to actually creating a type. If you are in typescript, and you need a type. you don't want a declaration, you want a concrete type. Feel free to put it another file, but that's a .ts file, not a d.ts file.

TLDR declare is a keyword to tell the TS compiler that something already exists, not to make it. If you are in a typescript project trying to define a type. you should not be using the declare keyword. and you shouldn't be using the .d.ts extension. You are misunderstanding the purpose.

RickeyWard avatar Oct 04 '20 22:10 RickeyWard

i am using @rebass/forms in as one of the dependency, when i import any component from @rebass/forms, it throws : Could not find a declaration file for module '@rebass/forms'. Where do i correctly define the types?

my folder structure is src/component/component.tsx

defining module @rebass/forms in src/typings.d.ts is not working also tried in component/types.d.ts

Can someone please help, where to declare the typings? Thanks in advance

jishnukoottala avatar Oct 07 '20 09:10 jishnukoottala

After hours of chasing this issue, i got a solution that worked:

in tsconfig.json add baseUrl in compilerOptions property

"baseUrl": ".",
    "paths": {
      "*": ["src/types/*"]
    }

create a new file in types folder -> overrides.d.ts declare module '@rebass/forms'

jishnukoottala avatar Oct 08 '20 06:10 jishnukoottala