A
A
Arthur2021-09-27 16:03:36
typescript
Arthur, 2021-09-27 16:03:36

Why is the wrong type returned?

Hello!
There is such an interface

export interface DocExportRequest {
  id: string
  type: 'PDF' | 'CSV'
  [k: string]: any
}


Written generic leaving only real-life properties
// see https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-414782407
// disables `[k: string]: any;` indexing
export type KnownKeys<T> = {
  [K in keyof T]: string extends K ? never : number extends K ? never : K
} extends { [_ in keyof T]: infer U }
  ? U
  : never


Used ForkTsCheckerWebpackPlugin with these settings

const config = {
  async: isDevelopment,
  useTypescriptIncrementalApi: true,
  checkSyntacticErrors: true,
  reportFiles: ['**', '!**/__tests__/**', '!**/?(*.)(spec|test).*', '!**/src/setupProxy.*', '!**/src/setupTests.*'],
  silent: true,
};


and such a tsconfig
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@assets/*": ["src/assets/*"],
      "@src/*": ["src/*"]
   },
    "outDir": "./dist/",
    "sourceMap": true,
    "noImplicitAny": true,
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "typeRoots": [
      "./node_modules/@types"
    ],
    "types": [
      "node",
      "webpack-env",
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "jsx": "react"
  },
  "include": ["src", "public"]
}


When trying to apply KnownKeys to the DocExportRequest interface, I
type TDocExportReq = KnownKeys<DocExportRequest>
expect that
type TDocExportReq {
  id: string
  type: 'PDF' | 'CSV'
}

But it returns 'never'. Why is this happening?

Prior to this, this project was on create-react-app with the same configs, and the types were correctly distinguished.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Arthur, 2021-09-27
@cloudz

This is "broken" in new versions of typescript. https://github.com/microsoft/TypeScript/issues/44143
In versions ^4.2, you can use alternative solutions, for example

type KnownKeys<T> = keyof { [P in keyof T as
    string extends P ? never : number extends P ? never : P
    ]: T[P]; };

or
type KeyToKeyNoIndex<T> = {
  [K in keyof T]: string extends K ? never : number extends K ? never : K;
};
type ValuesOf<T> = T extends { [K in keyof T]: infer U; } ? U : never;
export type KnownKeys<T> = ValuesOf<KeyToKeyNoIndex<T>>;

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question