typings / discussions

For discussions and issues with Typings or TypeScript definitions
7 stars 0 forks source link

Best way to export interfaces for a module that only has a default export #9

Open hodavidhara opened 8 years ago

hodavidhara commented 8 years ago

This is more a question about writing type definitions than about typings, feel free to let me know if I should post this elsewhere!

I've been working on the type definitions for Griddle, which only exports a React class, essentially to be used like so:

import * as React from 'react';
import { render } from 'react-dom';
import Griddle from 'griddle-react';

render(
  <Griddle />,
  document.getElementById('root')
);

There are some interfaces in my definition that would be really great for a developer to be able to consume, but I haven't found a good way to make it available. If I simply export them along side the true default export, they need to access it in a way that doesn't look so great:

import {default as Griddle, CustomColumnComponentProps} from 'griddle-react';

If I was able to declare a namespace that contained the interface that wasn't wrapped by typings in the ambient module declaration, they could gain direct access to the interface. Something resulting like:

declare namespace GriddleReact {
    export interface GriddleProps {
        someProp: string;
    }
}
declare module 'griddle-react' {
    export default class Griddle extends React.Component<GriddleReact.GriddleProps, any> {}
}

which could then be used like:

import Griddle from 'griddle-react';
var someProps: GriddleReact.GriddleProps = {someProp: 'prop'};

Is this frowned upon because it pollutes the environment with a namespace that the consumer may not be expecting? Any other thoughts or good ways to do this?

blakeembrey commented 8 years ago

Is this frowned upon because it pollutes the environment with a namespace that the consumer may not be expecting?

Yes.

Any other thoughts or good ways to do this?

If this is ES6 style with a default export, do how it currently is. Just export alongside the default export. Also, the syntax you're using could be simpler since it's an ES6 import: import Griddle, { CustomColumnComponentProps } from 'griddle-react'. That's what I would normally do, there's no namespacing issues and it's all on the users to do what they want. Does that help?

For ES5/CommonJS modules using module.exports, the type definition is usually a slightly different but similar pattern using a namespace.

declare function main (options: main.Options): void;

declare namespace main {
  export interface Options {}
}

export = main;
hodavidhara commented 8 years ago

Ah I had forgotten about the syntax that allows for both default and destructuring, that does make it nicer! I guess I didn't like it because it seems a little misleading to look like you're importing something that doesn't actually exist in the library and is purely defined in the typings, but I guess there is no getting around that.