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

Set a type guard for hasOwnProperty signature. #18282

Closed
ezequiel-umu opened this issue Sep 6, 2017 · 4 comments
Closed

Set a type guard for hasOwnProperty signature. #18282

ezequiel-umu opened this issue Sep 6, 2017 · 4 comments
Labels
Declined The issue was declined as something which matches the TypeScript vision Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Suggestion An idea for TypeScript

Comments

@ezequiel-umu
Copy link

ezequiel-umu commented Sep 6, 2017

TypeScript Version: 2.5.0-dev.20170629

Watch this code with a new version of hasOwnProperty:

function hasOwnProperty<T, K extends keyof T>(object: T, key: string): key is K {
  return object.hasOwnProperty(key);
}

const x = {
  a: "a",
  b: "b",
};

// Ensure k is unknown for the transpiler:
const k = String.fromCharCode("a".charCodeAt(0) + 1);

// This is working without any problem.
if (hasOwnProperty(x, k)) {
  x[k] = "anything";
}

// This blames: file: 'Element implicitly has an 'any' type because type '{ a: string; b: string; }' has no index 
if (x.hasOwnProperty(k)) {
  x[k] = "anything";
}

// This emits the same error:
if (k in x) {
  x[k] = "anything";
}

Suggestion:

Change the actual declaration of hasOwnProperty:

hasOwnProperty(v: PropertyKey): boolean;

With a new one type guarded:

hasOwnProperty<T, K extends keyof T>(this: T, key: string): key is K;

Something that also could be added is a type guard to in operator to work as the type guard of the suggested hasOwnProperty .

@mhegazy
Copy link
Contributor

mhegazy commented Sep 6, 2017

you do not need the K type parameter. a simplified version would be:

   hasOwnProperty<T>(this: T, v: PropertyKey): v is keyof T;

@mhegazy
Copy link
Contributor

mhegazy commented Sep 6, 2017

The use of in is tracked by #10485

@mhegazy mhegazy added Help Wanted You can do this Suggestion An idea for TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript and removed Help Wanted You can do this labels Sep 6, 2017
@mhegazy
Copy link
Contributor

mhegazy commented Sep 6, 2017

similar discussion can be found in #12253 (comment)

@mhegazy mhegazy added the Declined The issue was declined as something which matches the TypeScript vision label Sep 6, 2017
@mhegazy mhegazy closed this as completed Sep 6, 2017
@DanielRosenwasser
Copy link
Member

This really isn't appropriate. At runtime, your object might have more keys than T describes, so the sort of information you're trying to convey to the type system wouldn't be true.

There are two things that this function gives information about:

  1. Some value x of type T also has a property key K (i.e. x is T & Record<K, any>).
  2. Some value x of type T that has an optionally defined key of type U (i.e. T extends Partial<Record<K, U>> ) actually has that property defined (i.e. x is T & Record<K, U>).

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Declined The issue was declined as something which matches the TypeScript vision Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants