Skip to content

Commit b864600

Browse files
committed
feat: improve hasOwnProperty types
fixes #4
1 parent 1e311d0 commit b864600

File tree

7 files changed

+279
-70
lines changed

7 files changed

+279
-70
lines changed

build/replacement.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const replacement = new Map([
1111
"ReadonlyArray",
1212
"Array",
1313
"PromiseConstructorLike",
14+
"Object",
1415
]),
1516
],
1617
[
@@ -50,4 +51,5 @@ export const replacement = new Map([
5051
["es2019.object.d.ts", new Set(["ObjectConstructor"])],
5152
["es2021.promise.d.ts", new Set(["AggregateError"])],
5253
["es2021.string.d.ts", new Set(["String"])],
54+
["es2022.object.d.ts", new Set(["ObjectConstructor"])],
5355
]);

generated/lib.es2022.object.d.ts

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,30 @@
1-
interface ObjectConstructor {
2-
/**
3-
* Determines whether an object has a property with the specified name.
4-
* @param o An object.
5-
* @param v A property name.
6-
*/
7-
hasOwn(o: object, v: PropertyKey): boolean;
8-
}
1+
interface ObjectConstructor {
2+
/**
3+
* Determines whether an object has a property with the specified name.
4+
* @param o An object.
5+
* @param v A property name.
6+
*/
7+
hasOwn<Key extends PropertyKey>(
8+
o: object,
9+
v: Key
10+
): o is string extends Key
11+
? {}
12+
: number extends Key
13+
? {}
14+
: symbol extends Key
15+
? {}
16+
: Key extends PropertyKey
17+
? { [key in Key]: unknown }
18+
: {};
19+
}
20+
// --------------------
21+
22+
// interface ObjectConstructor {
23+
// /**
24+
// * Determines whether an object has a property with the specified name.
25+
// * @param o An object.
26+
// * @param v A property name.
27+
// */
28+
// hasOwn(o: object, v: PropertyKey): boolean;
29+
// }
30+

generated/lib.es5.d.ts

Lines changed: 88 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,53 @@ type UnionToIntersection<T> = (
1515
*/
1616
declare function eval(x: string): unknown;
1717

18+
interface Object {
19+
/** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
20+
constructor: Function;
21+
22+
/** Returns a string representation of an object. */
23+
toString(): string;
24+
25+
/** Returns a date converted to a string using the current locale. */
26+
toLocaleString(): string;
27+
28+
/** Returns the primitive value of the specified object. */
29+
valueOf(): Object;
30+
31+
/**
32+
* Determines whether an object has a property with the specified name.
33+
* @param v A property name.
34+
*/
35+
hasOwnProperty<Key extends PropertyKey>(
36+
v: Key
37+
): this is string extends Key
38+
? {}
39+
: number extends Key
40+
? {}
41+
: symbol extends Key
42+
? {}
43+
: Key extends PropertyKey
44+
? { [key in Key]: unknown }
45+
: {};
46+
47+
/**
48+
* Determines whether an object exists in another object's prototype chain.
49+
* @param v Another object whose prototype chain is to be checked.
50+
*/
51+
isPrototypeOf(v: Object): boolean;
52+
53+
/**
54+
* Determines whether a specified property is enumerable.
55+
* @param v A property name.
56+
*/
57+
propertyIsEnumerable(v: PropertyKey): boolean;
58+
}
59+
60+
/**
61+
* Provides functionality common to all JavaScript objects.
62+
*/
63+
declare var Object: ObjectConstructor;
64+
1865
interface ObjectConstructor {
1966
new (value?: any): Object;
2067
(): {};
@@ -848,39 +895,41 @@ interface PropertyDescriptor {
848895

849896
interface PropertyDescriptorMap {
850897
[key: PropertyKey]: PropertyDescriptor;
851-
}
852-
853-
interface Object {
854-
/** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
855-
constructor: Function;
856-
857-
/** Returns a string representation of an object. */
858-
toString(): string;
859-
860-
/** Returns a date converted to a string using the current locale. */
861-
toLocaleString(): string;
862-
863-
/** Returns the primitive value of the specified object. */
864-
valueOf(): Object;
865-
866-
/**
867-
* Determines whether an object has a property with the specified name.
868-
* @param v A property name.
869-
*/
870-
hasOwnProperty(v: PropertyKey): boolean;
871-
872-
/**
873-
* Determines whether an object exists in another object's prototype chain.
874-
* @param v Another object whose prototype chain is to be checked.
875-
*/
876-
isPrototypeOf(v: Object): boolean;
877-
878-
/**
879-
* Determines whether a specified property is enumerable.
880-
* @param v A property name.
881-
*/
882-
propertyIsEnumerable(v: PropertyKey): boolean;
883898
}
899+
//
900+
//
901+
// interface Object {
902+
// /** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
903+
// constructor: Function;
904+
//
905+
// /** Returns a string representation of an object. */
906+
// toString(): string;
907+
//
908+
// /** Returns a date converted to a string using the current locale. */
909+
// toLocaleString(): string;
910+
//
911+
// /** Returns the primitive value of the specified object. */
912+
// valueOf(): Object;
913+
//
914+
// /**
915+
// * Determines whether an object has a property with the specified name.
916+
// * @param v A property name.
917+
// */
918+
// hasOwnProperty(v: PropertyKey): boolean;
919+
//
920+
// /**
921+
// * Determines whether an object exists in another object's prototype chain.
922+
// * @param v Another object whose prototype chain is to be checked.
923+
// */
924+
// isPrototypeOf(v: Object): boolean;
925+
//
926+
// /**
927+
// * Determines whether a specified property is enumerable.
928+
// * @param v A property name.
929+
// */
930+
// propertyIsEnumerable(v: PropertyKey): boolean;
931+
// }
932+
884933
//
885934
//
886935
// interface ObjectConstructor {
@@ -994,13 +1043,15 @@ interface Object {
9941043
// */
9951044
// keys(o: object): string[];
9961045
// }
1046+
1047+
//
1048+
//
1049+
// /**
1050+
// * Provides functionality common to all JavaScript objects.
1051+
// */
1052+
// declare var Object: ObjectConstructor;
9971053

9981054

999-
/**
1000-
* Provides functionality common to all JavaScript objects.
1001-
*/
1002-
declare var Object: ObjectConstructor;
1003-
10041055
/**
10051056
* Creates a new function.
10061057
*/

lib/lib.es2022.object.d.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
interface ObjectConstructor {
2+
/**
3+
* Determines whether an object has a property with the specified name.
4+
* @param o An object.
5+
* @param v A property name.
6+
*/
7+
hasOwn<Key extends PropertyKey>(
8+
o: object,
9+
v: Key
10+
): o is string extends Key
11+
? {}
12+
: number extends Key
13+
? {}
14+
: symbol extends Key
15+
? {}
16+
: Key extends PropertyKey
17+
? { [key in Key]: unknown }
18+
: {};
19+
}

lib/lib.es5.d.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,53 @@ type UnionToIntersection<T> = (
1515
*/
1616
declare function eval(x: string): unknown;
1717

18+
interface Object {
19+
/** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
20+
constructor: Function;
21+
22+
/** Returns a string representation of an object. */
23+
toString(): string;
24+
25+
/** Returns a date converted to a string using the current locale. */
26+
toLocaleString(): string;
27+
28+
/** Returns the primitive value of the specified object. */
29+
valueOf(): Object;
30+
31+
/**
32+
* Determines whether an object has a property with the specified name.
33+
* @param v A property name.
34+
*/
35+
hasOwnProperty<Key extends PropertyKey>(
36+
v: Key
37+
): this is string extends Key
38+
? {}
39+
: number extends Key
40+
? {}
41+
: symbol extends Key
42+
? {}
43+
: Key extends PropertyKey
44+
? { [key in Key]: unknown }
45+
: {};
46+
47+
/**
48+
* Determines whether an object exists in another object's prototype chain.
49+
* @param v Another object whose prototype chain is to be checked.
50+
*/
51+
isPrototypeOf(v: Object): boolean;
52+
53+
/**
54+
* Determines whether a specified property is enumerable.
55+
* @param v A property name.
56+
*/
57+
propertyIsEnumerable(v: PropertyKey): boolean;
58+
}
59+
60+
/**
61+
* Provides functionality common to all JavaScript objects.
62+
*/
63+
declare var Object: ObjectConstructor;
64+
1865
interface ObjectConstructor {
1966
new (value?: any): Object;
2067
(): {};

tests/src/es2022.object.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { expectError, expectType } from "tsd";
2+
3+
// ObjectConstructor
4+
{
5+
// https://github.com/uhyo/better-typescript-lib/issues/4
6+
const obj: object = {};
7+
if (Object.hasOwn(obj, "foo")) {
8+
expectType<unknown>(obj.foo);
9+
expectType<{ foo: unknown }>(obj);
10+
}
11+
const obj2 = { foo: 123 };
12+
if (Object.hasOwn(obj2, "bar")) {
13+
expectType<unknown>(obj2.bar);
14+
expectType<{ foo: number } & { bar: unknown }>(obj2);
15+
}
16+
const obj3 = () => {};
17+
if (Object.hasOwn(obj3, "baz")) {
18+
expectType<unknown>(obj3.baz);
19+
expectType<(() => void) & { baz: unknown }>(obj3);
20+
}
21+
22+
const emptyObj = {};
23+
const key = Math.random() ? "foo" : "bar";
24+
if (Object.hasOwn(emptyObj, key)) {
25+
expectError(emptyObj.foo);
26+
expectError(emptyObj.bar);
27+
expectType<{ foo: unknown } | { bar: unknown }>(emptyObj);
28+
}
29+
const key2: string = "123";
30+
if (Object.hasOwn(emptyObj, key2)) {
31+
expectType<{}>(emptyObj);
32+
}
33+
}

0 commit comments

Comments
 (0)