Error:(19, 35) TS2304: Cannot find name 'T'. Why I can't extend interface in TS?

Viewed 20218

I want to extend an interface for React props. But I get TS error Error:(19, 35) TS2304: Cannot find name 'T'.

1) Why error? <T> is generic type. It can't be declared before usage.

2) Why TS throws error in my code but doesn't throw for DefinitelyTyped React types definitions here. Generic types <T> and many others are used everywhere in their code. Why they do not throw?

3) How to extend it the right way?

Here is my code.

I import interface Props from DefinitelyTyped for React:

import React, {Props, PureComponent} from 'react';

// TS throws Error:(20, 27) TS2304: Cannot find name 'T'.
interface IHomeProps extends Props<T> { }

class Home extends PureComponent<IHomeProps> {
  render() {
    ...
  }
}

// interface Props definition
    interface Props<T> {
        children?: ReactNode;
        key?: Key;
        ref?: LegacyRef<T>;
    }
2 Answers

You either need to specify a concrete T or declare a generic type parameter on the interface you are defining.

In react definitions the code works because they do define T the <T> after the interface is the definition for T, so it can then be used inside the interface. When you define your own interface, you need to define your own type parameter T and then forward if to Props. This is what a version that defined T would look like:

interface IHomeProps<T> extends Props<T> { }
                 //  ^ T is defined   ^ T is used

You probably want to just give a concrete type for T:

interface IHomeProps extends Props<HTMLDivElement> { }

class Home extends PureComponent<IHomeProps> {
    render() {
        return <div></div>
    }
}

Simple function example. Just extend the ObjectLiteral type.

Before:

private filterNull(data: Array<any>) {
    return data.filter(x => !!x);
}

After:

private filterNull<T extends ObjectLiteral>(data: Array<T>): Array<T> {
    return data.filter(x => !!x);
}
Related