#TS7006 even though type is defined on props

1 messages · Page 1 of 1 (latest)

rare merlin
#

Given the following types:

export type OrderHistoryTableProps = {
  data: OrderRow[];
  noDataText?: string;
} & SortParams &
  FilterParams &
  SearchParams;

type SortParams = AllOrNone<{
  sorting: SortingState;
  onSortChange: (state: SortingState) => void;
}>;

type FilterParams = AllOrNone<{
  filter: ColumnFiltersState;
  onFilterChange: (state: ColumnFiltersState) => void;
}>;

type SearchParams = AllOrNone<{
  search: string;
  onSearchChange: (value: string) => void;
}>;

function OrderHistoryTable({
  data,
  noDataText = "No orders to display!",
  onFilterChange,
  onSortChange,
  sorting,
  filter,
  search,
  onSearchChange,
}: OrderHistoryTableProps): JSX.Element {
  ...
}

I seem to be getting a TS7006 error when calling the component and defining the onSearchChange function in-line:

<OrderHistoryTable
  data={rowData}
  {...{ sorting, filter, search }}
  onSortChange={onSortChange}
  onFilterChange={setFilter}
  onSearchChange={(value) => setSearch(value)} // TS7006: Parameter 'value' implicitly has an 'any' type.
/>

However, onSearchChange is explicitely defined as onSearchChange: (value: string) => void; in the prop type. This worked fine in Typescript 4.9.5, but in 5.1.6 this seems to be an error. Can anyone help me understand why this is occurring?

tsconfig:

// apps/web/tsconfig.json
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "target": "ES6",
    "lib": ["dom", "dom.iterable", "ES6"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "CommonJS",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "jsxImportSource": "@emotion/react",
    "noEmitOnError": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "sourceMap": true,
    "baseUrl": "./",
    "composite": true,
    "outDir": "./dist",
    "paths": {
      "@/*": ["./*"],
      "@components/*": ["./src/components/*"],
      "@layouts/*": ["./src/layouts/*"],
      "@codegen/*": ["./@types/codegen/*"]
    }
  },
  "ts-node": {
    "compilerOptions": {
      "isolatedModules": false,
      "module": "CommonJS"
    }
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    "./.storybook/*",
    "public/*",
    "**/*.js"
  ],
  "exclude": ["node_modules", "cypress"]
}
// <root>/tsconfig.json
{
  "extends": "@tsconfig/node16/tsconfig.json",

  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Node 16",

  "compilerOptions": {
    "allowJs": true,
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitAny": true,
    "noEmitOnError": true
  },
  "references": [
    { "path": "apps/web" },
    {
      "path": "apps/server"
    }
  ],
  "exclude": ["node_modules"]
}
lilac patrol
#

Interesting, what is AllOrNone, is it a built-in helper or your custom defined type?

rare merlin
#

export type AllOrNone<T> = T | { [K in keyof T]?: never };
It's a type I defined that ensures both keys are present or neither should be present

#

Forgot to include that

#

Interestingly though, I tried reverting to 4.9.5 and looked at it in VS Code as well as Webstorm, and Webstorm does NOT throw and error while VS Code does (even in 4.9.5) 🤔

lilac patrol
#

hm, do those IDEs use their own configs? You could also try tsc --project tsconfig.json --noEmit to get a third opinion 🙂

rare merlin
#

What's really weird is this:

#

So it still sees what the type is of the prop, but for some reason cannot attribute it to the inline function

#

Ohhhhhhh

#

Removing the AllOrNone type wrapper actually fixed it 🤔

#

Now why would that be the case

lilac patrol
#

I though it looked weird

#

can you try this type AllOrNone<T> = T extends { [key: string]: never } ? never : T;

#

this one is a bit more permissive

rare merlin
#

Yeah that still achieves the functionality that I want and also removes the error!

lilac patrol
#

I though maybe your version AllOrNone cancelles each other out when used with &

rare merlin
#

Actually no it doesn't

#

If neither search or onSearchChange are provided, an error should not be thrown

lilac patrol
#

I see

rare merlin
#

That's why the type is called AllOrNone, as we want both provided or neither provided

lilac patrol
#

well maybe just get rid of AllOrNone

#

I don't see how it hekps in this specific case

rare merlin
#

Because it's a reusable component that doesn't always need each of those props

#

But if you do provide one, the other should also be provided

#

It's just weird that I'm only just running into this issue now. Caught it when trying to build NextJS

lilac patrol
#

can't that be achieved with using | ?

rare merlin
#

Has been building fine up until I finally decided to upgrade to 5.1.6 from 4.9.5

rare merlin
lilac patrol
#

kinda like

export type OrderHistoryTableProps = {
  data: OrderRow[];
  noDataText?: string;
} & (
  {
    sorting: SortingState;
    onSortChange: (state: SortingState) => void;
  } | {
    filter: ColumnFiltersState;
    onFilterChange: (state: ColumnFiltersState) => void;
  } | {
    search: string;
    onSearchChange: (value: string) => void;
  }
);
#

but that will of course only allow one of them

#

so I guess no

rare merlin
#

I was essentially trying to create a wrapper type for use elsewhere, and I guess also trying to be fancy. But yes I could probably do that.

#

Oh wait, that would not work as it wouldn't accept if none were provided

#

Maybe if wrapped in a partial

#

Ah no, that also doesn't work as then the props then report as not existing

lilac patrol
#

funny thing, this simplified version of your code does work for me (on 5.1.2)

rare merlin
#

What does your tsconfig look like?

#

Ok now THAT is weird. After monkeying around with the types and reverting them to what they once were... it reports fine

#

Only difference is I am no longer using the object spread on the props

lilac patrol
#

I basically copied your config

#

yeah, maybe it has to do with that spread...

rare merlin
#

That is so weird

#

Yeah as soon as I remove the spread operator, it's fine

#

Welp, thanks for coming along on this journey with me

#

I wonder if I should file a bug report

lilac patrol
#

np, let me know if you undersand why

rare merlin
#

Was able to recreate it