Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect narrowing of functions with keyof parameters #430

Open
fergusean opened this issue Apr 8, 2023 · 1 comment
Open

Incorrect narrowing of functions with keyof parameters #430

fergusean opened this issue Apr 8, 2023 · 1 comment

Comments

@fergusean
Copy link
Contributor

When omitting [props whose values are functions] from a type, if the function includes a keyof X parameter, the TS type is correctly narrowed, but the runtime type still includes that prop.

Sandbox: https://replit.com/@fergusean/DKTypeIssueDemo2

Code:

import { typeOf, ReflectionKind } from '@deepkit/type';

export class SomeClass {
  fieldA!: string;
  fieldB!: number;
  fieldC!: boolean;

  someFunctionA() { }
  someFunctionB(input: string) { }
  someFunctionC(input: keyof this /* behaves the same with keyof anything */) { }
}

export type ArrowFunction = (...args: any) => any;
type MethodKeys<T> = {
  [K in keyof T]: T[K] extends ArrowFunction ? K : never
}[keyof T];
export type EntityFields<T extends object> = Omit<T, MethodKeys<T>>;

function typeTest(): EntityFields<SomeClass> {
  return null as any;
}

const theType = typeOf<typeof typeTest>();
console.log(theType.kind === ReflectionKind.function && theType.return);

// output yields subtypes fieldA, fieldB, fieldC, and someFunctionC
// the TS type does NOT include someFunctionC

Output:

$ ts-node index.ts
<ref *1> {
  kind: 30,
  typeName: 'EntityFields',
  typeArguments: [
    {
      kind: 20,
      classType: [Function],
      types: [Array],
      typeArguments: undefined
    }
  ],
  types: [
    {
      kind: 32,
      name: 'fieldA',
      type: [Object],
      optional: undefined,
      parent: [Object]
    },
    {
      kind: 32,
      name: 'fieldB',
      type: [Object],
      optional: undefined,
      parent: [Object]
    },
    {
      kind: 32,
      name: 'fieldC',
      type: [Object],
      optional: undefined,
      parent: [Object]
    },
    {
      kind: 32,
      name: 'someFunctionC',
      type: [Object],
      optional: undefined,
      parent: [Object]
    }
  ],
  originTypes: [
    { typeName: 'Omit', typeArguments: [Array] },
    { typeName: 'Pick', typeArguments: [Array] }
  ],
  parent: {
    kind: 17,
    name: 'typeTest',
    return: [Circular *1],
    parameters: [],
    function: [Function: typeTest] { __type: [Array] }
  }
}
marcj added a commit that referenced this issue Apr 12, 2023
@marcj
Copy link
Member

marcj commented Apr 12, 2023

Unfortunately, reference to this is not implemented at all in our type compiler, so referring to it breaks stuff in unexpected ways. I've added now a workaround that keyof this is handled as any (instead of never), so that your code should work. Please test and let me know! Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants