4

I am trying to add a type definition to a .d.ts file for a React.FunctionComponent that looks like this:

Tree.propTypes = {
  root: PropTypes.object.isRequired,
  children: PropTypes.func,
  top: PropTypes.number,
  left: PropTypes.number,
  className: PropTypes.string,
  size: PropTypes.arrayOf(PropTypes.number),
  nodeSize: PropTypes.arrayOf(PropTypes.number),
  separation: PropTypes.func,
  linkComponent: PropTypes.any,
  nodeComponent: PropTypes.any
};

export default function Tree({
  top,
  left,
  className,
  root,
  size,
  nodeSize,
  separation,
  children,
  linkComponent = DefaultLink,
  nodeComponent = DefaultNode,
  ...restProps
}) {

import React from 'react'; import { TreeLayout, HierarchyPointNode, HierarchyNode } from 'd3-hierarchy';

I have come up with this approach:

export interface TreeProps<Datum, LinkComponentType = any, NodeComponentType = any> {
  root: HierarchyNode<Datum>;
  top?: number;
  left?: number;
  className?: string;
  size?: [number, number];
  linkComponent: React.ComponentType<LinkComponentType>;
  separation: (a: HierarchyPointNode<Datum>, b: HierarchyPointNode<Datum>) => number;
  nodeComponent: React.ComponentType<NodeComponentType>;
  nodeSize?: [number, number];
}


export declare function Tree<
  Datum,
  LinkComponentType = any,
  NodeComponentType = any
>(args: TreeProps<Datum, LinkComponentType, NodeComponentType>): JSX.Element;

Is this the correct way of typing this, I think it should be a React.FunctionComponent like:

export declare const Tree<Datum>

But then I would not be able to pass in the type arguments.

dagda1
  • 26,856
  • 59
  • 237
  • 450
  • Why do you use the declare keyword here? – Avin Kavish Jun 08 '19 at 07:07
  • do `linkComponent` and `nodeComponent` impact the props available to the component ? It would seem like they would. Otherwise `export declare function` seems ok, if you want to use a `const` it should be `export declare const Tree: < Datum, LinkComponentType = any, NodeComponentType = any >(args: TreeProps) => JSX.Element;` But I see no need to do this, they should work the same in this case – Titian Cernicova-Dragomir Jun 09 '19 at 07:32

3 Answers3

2

You can declare a module in .d.ts:

declare module 'NAME_OF_THE_PACKAGE' {
    export interface TreeProps<Datum, LinkComponentType = any, NodeComponentType = any> {
        root: HierarchyNode<Datum>;
        top?: number;
        left?: number;
        className?: string;
        size?: [number, number];
        linkComponent: React.ComponentType<LinkComponentType>;
        separation: (a: HierarchyPointNode<Datum>, b: HierarchyPointNode<Datum>) => number;
        nodeComponent: React.ComponentType<NodeComponentType>;
        nodeSize?: [number, number];
    }

    export function Tree<Datum, LinkComponentType = any, NodeComponentType = any>(
        args: TreeProps<Datum, LinkComponentType, NodeComponentType>
    ): JSX.Element;
}

Where NAME_OF_THE_PACKAGE is exactly the name you import the package or install it via npm or yarn.

This way, you will be able to import TreeProps and Tree this way

import { TreeProps, Tree } from 'NAME_OF_THE_PACKAGE'

You can read more about modules here (check the example of how JavaScript libs are declared - "Working with Other JavaScript Libraries").

Pedro Arantes
  • 5,113
  • 5
  • 25
  • 60
0

You can declare a type like this

export type Tree<D, LC = any, NC = any> =
    React.FunctionComponent<TreeProps<D, LC, NC>> => JSX.Element

Usage

const Tree: Tree<a,b,c> = (props) => <></>
Avin Kavish
  • 8,317
  • 1
  • 21
  • 36
0

You can do

declare const Tree: React.FunctionComponent<TreeProps<Datum, LinkComponentType, NodeComponentType>>;

export default Tree;

Tree will be of type React.FunctionComponent<P> which is (props: PropsWithChildren<P>, context?: any): ReactElement | null; (function component).

May be you've been confused by declare keyword. The best description I found is here.

To create function of type React.FunctionComponent<P> use syntax

const Tree: React.FunctionComponent<TreeProps<Datum, LinkComponentType, NodeComponentType>> =
(props) => {
    return <div className={props.className}>
        Some div
        </div>
}

Note that here is no need for declare keyword.

Fyodor Yemelyanenko
  • 11,264
  • 1
  • 30
  • 38
  • i am creating a declaration file for a 3rd party so there is s need – dagda1 Jun 08 '19 at 09:57
  • Sorry, I didn't understand you comment. You mean 'so there is I need' or 'so there is no need'? – Fyodor Yemelyanenko Jun 08 '19 at 10:27
  • i’m writing a declaration file index.d.ts for a 3rd party library that does not have a declaration file. are you still saying i dint need declare – dagda1 Jun 08 '19 at 10:28
  • To declare types for third party lib you should use `declare` keyword. First code snippet should suit your needs. Code snippet without `decalre` is to difference between declaring and implementing Function component – Fyodor Yemelyanenko Jun 08 '19 at 11:10