Skip to content

Commit

Permalink
feat: improve hasOwnProperty types
Browse files Browse the repository at this point in the history
fixes #4
  • Loading branch information
uhyo committed Apr 29, 2022
1 parent 1e311d0 commit b864600
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 70 deletions.
2 changes: 2 additions & 0 deletions build/replacement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const replacement = new Map([
"ReadonlyArray",
"Array",
"PromiseConstructorLike",
"Object",
]),
],
[
Expand Down Expand Up @@ -50,4 +51,5 @@ export const replacement = new Map([
["es2019.object.d.ts", new Set(["ObjectConstructor"])],
["es2021.promise.d.ts", new Set(["AggregateError"])],
["es2021.string.d.ts", new Set(["String"])],
["es2022.object.d.ts", new Set(["ObjectConstructor"])],
]);
38 changes: 30 additions & 8 deletions generated/lib.es2022.object.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
interface ObjectConstructor {
/**
* Determines whether an object has a property with the specified name.
* @param o An object.
* @param v A property name.
*/
hasOwn(o: object, v: PropertyKey): boolean;
}
interface ObjectConstructor {
/**
* Determines whether an object has a property with the specified name.
* @param o An object.
* @param v A property name.
*/
hasOwn<Key extends PropertyKey>(
o: object,
v: Key
): o is string extends Key
? {}
: number extends Key
? {}
: symbol extends Key
? {}
: Key extends PropertyKey
? { [key in Key]: unknown }
: {};
}
// --------------------

// interface ObjectConstructor {
// /**
// * Determines whether an object has a property with the specified name.
// * @param o An object.
// * @param v A property name.
// */
// hasOwn(o: object, v: PropertyKey): boolean;
// }

125 changes: 88 additions & 37 deletions generated/lib.es5.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,53 @@ type UnionToIntersection<T> = (
*/
declare function eval(x: string): unknown;

interface Object {
/** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
constructor: Function;

/** Returns a string representation of an object. */
toString(): string;

/** Returns a date converted to a string using the current locale. */
toLocaleString(): string;

/** Returns the primitive value of the specified object. */
valueOf(): Object;

/**
* Determines whether an object has a property with the specified name.
* @param v A property name.
*/
hasOwnProperty<Key extends PropertyKey>(
v: Key
): this is string extends Key
? {}
: number extends Key
? {}
: symbol extends Key
? {}
: Key extends PropertyKey
? { [key in Key]: unknown }
: {};

/**
* Determines whether an object exists in another object's prototype chain.
* @param v Another object whose prototype chain is to be checked.
*/
isPrototypeOf(v: Object): boolean;

/**
* Determines whether a specified property is enumerable.
* @param v A property name.
*/
propertyIsEnumerable(v: PropertyKey): boolean;
}

/**
* Provides functionality common to all JavaScript objects.
*/
declare var Object: ObjectConstructor;

interface ObjectConstructor {
new (value?: any): Object;
(): {};
Expand Down Expand Up @@ -848,39 +895,41 @@ interface PropertyDescriptor {

interface PropertyDescriptorMap {
[key: PropertyKey]: PropertyDescriptor;
}

interface Object {
/** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
constructor: Function;

/** Returns a string representation of an object. */
toString(): string;

/** Returns a date converted to a string using the current locale. */
toLocaleString(): string;

/** Returns the primitive value of the specified object. */
valueOf(): Object;

/**
* Determines whether an object has a property with the specified name.
* @param v A property name.
*/
hasOwnProperty(v: PropertyKey): boolean;

/**
* Determines whether an object exists in another object's prototype chain.
* @param v Another object whose prototype chain is to be checked.
*/
isPrototypeOf(v: Object): boolean;

/**
* Determines whether a specified property is enumerable.
* @param v A property name.
*/
propertyIsEnumerable(v: PropertyKey): boolean;
}
//
//
// interface Object {
// /** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
// constructor: Function;
//
// /** Returns a string representation of an object. */
// toString(): string;
//
// /** Returns a date converted to a string using the current locale. */
// toLocaleString(): string;
//
// /** Returns the primitive value of the specified object. */
// valueOf(): Object;
//
// /**
// * Determines whether an object has a property with the specified name.
// * @param v A property name.
// */
// hasOwnProperty(v: PropertyKey): boolean;
//
// /**
// * Determines whether an object exists in another object's prototype chain.
// * @param v Another object whose prototype chain is to be checked.
// */
// isPrototypeOf(v: Object): boolean;
//
// /**
// * Determines whether a specified property is enumerable.
// * @param v A property name.
// */
// propertyIsEnumerable(v: PropertyKey): boolean;
// }

//
//
// interface ObjectConstructor {
Expand Down Expand Up @@ -994,13 +1043,15 @@ interface Object {
// */
// keys(o: object): string[];
// }

//
//
// /**
// * Provides functionality common to all JavaScript objects.
// */
// declare var Object: ObjectConstructor;


/**
* Provides functionality common to all JavaScript objects.
*/
declare var Object: ObjectConstructor;

/**
* Creates a new function.
*/
Expand Down
19 changes: 19 additions & 0 deletions lib/lib.es2022.object.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
interface ObjectConstructor {
/**
* Determines whether an object has a property with the specified name.
* @param o An object.
* @param v A property name.
*/
hasOwn<Key extends PropertyKey>(
o: object,
v: Key
): o is string extends Key
? {}
: number extends Key
? {}
: symbol extends Key
? {}
: Key extends PropertyKey
? { [key in Key]: unknown }
: {};
}
47 changes: 47 additions & 0 deletions lib/lib.es5.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,53 @@ type UnionToIntersection<T> = (
*/
declare function eval(x: string): unknown;

interface Object {
/** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
constructor: Function;

/** Returns a string representation of an object. */
toString(): string;

/** Returns a date converted to a string using the current locale. */
toLocaleString(): string;

/** Returns the primitive value of the specified object. */
valueOf(): Object;

/**
* Determines whether an object has a property with the specified name.
* @param v A property name.
*/
hasOwnProperty<Key extends PropertyKey>(
v: Key
): this is string extends Key
? {}
: number extends Key
? {}
: symbol extends Key
? {}
: Key extends PropertyKey
? { [key in Key]: unknown }
: {};

/**
* Determines whether an object exists in another object's prototype chain.
* @param v Another object whose prototype chain is to be checked.
*/
isPrototypeOf(v: Object): boolean;

/**
* Determines whether a specified property is enumerable.
* @param v A property name.
*/
propertyIsEnumerable(v: PropertyKey): boolean;
}

/**
* Provides functionality common to all JavaScript objects.
*/
declare var Object: ObjectConstructor;

interface ObjectConstructor {
new (value?: any): Object;
(): {};
Expand Down
33 changes: 33 additions & 0 deletions tests/src/es2022.object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expectError, expectType } from "tsd";

// ObjectConstructor
{
// https://github.com/uhyo/better-typescript-lib/issues/4
const obj: object = {};
if (Object.hasOwn(obj, "foo")) {
expectType<unknown>(obj.foo);
expectType<{ foo: unknown }>(obj);
}
const obj2 = { foo: 123 };
if (Object.hasOwn(obj2, "bar")) {
expectType<unknown>(obj2.bar);
expectType<{ foo: number } & { bar: unknown }>(obj2);
}
const obj3 = () => {};
if (Object.hasOwn(obj3, "baz")) {
expectType<unknown>(obj3.baz);
expectType<(() => void) & { baz: unknown }>(obj3);
}

const emptyObj = {};
const key = Math.random() ? "foo" : "bar";
if (Object.hasOwn(emptyObj, key)) {
expectError(emptyObj.foo);
expectError(emptyObj.bar);
expectType<{ foo: unknown } | { bar: unknown }>(emptyObj);
}
const key2: string = "123";
if (Object.hasOwn(emptyObj, key2)) {
expectType<{}>(emptyObj);
}
}
Loading

0 comments on commit b864600

Please sign in to comment.