ink-select-input icon indicating copy to clipboard operation
ink-select-input copied to clipboard

Typescript: cannot import Item component - type is imported instead

Open goliney opened this issue 5 years ago • 8 comments

index.test-d.tsx exports types and default value (InkSelectInput):

https://github.com/vadimdemedes/ink-select-input/blob/6e0f6f47cf2d85dc0a171814b2c95d18db985ea5/index.d.ts#L72-L75

However, it doesn't export Item and Indicator components. Because of that, an attempt to import Item from ink-select-input ends up with:

image

Error:

error TS2693: 'Item' only refers to a type, but is being used as a value here.

Code snippet used:

import React from 'react';
import SelectInput, { Item, InkSelectInputProps } from 'ink-select-input';

export function ChoicesComponent({ itemComponent = Item, items, onSubmit }: Props) {
  return <SelectInput 
    itemComponent={itemComponent} 
    items={items} 
    onSelect={onSubmit} 
  />;
}

type ChoiceValue = any;

interface ChoiceOption {
  key?: string;
  label: string;
  value: ChoiceValue;
}

interface Choices {
  message?: string;
  items: ChoiceOption[];
}

interface Props extends Choices {
  onSubmit: () => void;
  itemComponent?: InkSelectInputProps['itemComponent'];
}

goliney avatar Jul 23 '19 20:07 goliney

This component does export Item type, there's a mistake in your example:

export function ChoicesComponent({ itemComponent = Item, items, onSubmit }: Props) {

itemComponent = Item means Item is a default value for itemComponent, but it's only a TS type, it doesn't exist in runtime. Instead, you should declare itemComponent: Item in Props type.

vadimdemedes avatar Jul 28 '19 22:07 vadimdemedes

@vadimdemedes you got my intentions wrong. I want to import a component, not a type, and use it as a default parameter. But I can’t, because a type is imported instead.

goliney avatar Jul 29 '19 05:07 goliney

Hm, what would be a solution for this?

vadimdemedes avatar Sep 22 '19 20:09 vadimdemedes

To get Item as a type I had to setup my imports as such:

import SelectInput from 'ink-select-input';
import { Item } from 'ink-select-input/build/SelectInput';

guyellis avatar Aug 31 '20 19:08 guyellis

The issue seems to be that the export in index.ts is exporting the Item component form Item.ts instead of the Item interface from SelectInput.ts

https://github.com/vadimdemedes/ink-select-input/blob/544039928c6783be102843463c8622683c35a35c/src/index.ts#L5

I think this should actually be:

export { Item } from './SelectInput';
export { Props as ItemProps } from './Item';

eugirdor avatar Sep 15 '20 00:09 eugirdor

I think you can solve this via:

import {FC, ComponentType} from 'react';
import {ItemProps} from 'ink-select-input';

interface Props {
  itemComponent: ComponentType<ItemProps>
}

const MyCustomComponent: FC<Props> = ({itemComponent}) => ...;

vadimdemedes avatar Sep 19 '20 09:09 vadimdemedes

@guyellis I tried

import SelectInput from 'ink-select-input';
import { Item } from 'ink-select-input/build/SelectInput';

and have error

TS2307: Cannot find module 'ink-select-input/build/SelectInput' or its corresponding type declarations.

gustawdaniel avatar Sep 05 '23 08:09 gustawdaniel

Ok. I had

type Environment = 'beta' | 'production';

  const handleSelect = (item: { label: Environment, value: Environment}) => {
    props.setEnv(item.value)
  };

  const items:Array<{ label: Environment, value: Environment}> = [
    {
      label: 'beta',
      value: 'beta'
    },
    {
      label: 'production',
      value: 'production'
    },
  ];

  return <SelectInput items={items} onSelect={handleSelect} />;

and fixed by setting the label as a string

  const handleSelect = (item: { label: string, value: Environment}) => {
    props.setEnv(item.value)
  };

gustawdaniel avatar Sep 05 '23 08:09 gustawdaniel