Skip to content

Instantly share code, notes, and snippets.

@aztack
Forked from eps1lon/is-plain-object-typed.ts
Created February 6, 2024 04:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aztack/3ef6d80bcfaea8f12f6e2cb89f68b9c5 to your computer and use it in GitHub Desktop.
Save aztack/3ef6d80bcfaea8f12f6e2cb89f68b9c5 to your computer and use it in GitHub Desktop.
// jonschlinkert/is-object
type IsObjectObject<T> = T extends
| AnyArray
| AnyFunction
| boolean
| null
| number
| string
| symbol
| undefined
? false
: true;
// jonschlinkert/is-plain-object
type HasNoModifiedConstructor<
T extends Object
> = T["constructor"] extends AnyFunction ? true : false;
type HasNoModifiedPrototype<T extends Object> = IsObjectObject<
T["constructor"]["prototype"]
> extends true
? true
: false;
// T extends {isPrototypeOf: any} as a T.hasOwnProperty('isPrototypeOf')
type PrototypeHasObjectSpecificMethod<
T extends Object
> = T["constructor"]["prototype"] extends { isPrototypeOf: any } ? true : false;
// IsObjectObject<T> && HasNoModifiedConstructor<T> && HasNoModifiedPrototype<T> && PrototypeHasObjectSpecific<T>
type IsPlainObject<T> = IsObjectObject<T> extends true
? (HasNoModifiedConstructor<T> extends true
? (HasNoModifiedPrototype<T> extends true
? (PrototypeHasObjectSpecificMethod<T> extends true ? true : false)
: false)
: false)
: false;
// no :(
type IsPlainActuallyPlain = IsPlainObject<{}>; // $ExpectType true
type ObjectIsPlain = IsPlainObject<object> // $ExpectType true
const obj = {}
// no :(
type IsValueObjectPlain = IsPlainObject<typeof a>; // $ExpectType true
declare function isPlainObject(obj: any): boolean;
function takePlainObject<T>(obj: T): IsObjectObject<T> extends true ? number : never {
if (!isPlainObject(obj)) {
throw new Error('gib me plain');
}
// @ts-ignore
return 1;
}
type ForcePlain<T> = IsObjectObject<T> extends true ? T : never;
function takeForcedPlainObject<T>(obj: ForcePlain<T>): number {
if (!isPlainObject(obj)) {
throw new Error('gib me plain');
}
return 1;
}
const good = takePlainObject({});
// no compile error but at least never
const bad = takePlainObject([]);
// typescript infers T to be {}
const badForced = takeForcedPlainObject([]);
// $ExpectError
const hintedBadForced = takeForcedPlainObject<any[]>([]);
const anArray: number[] = [];
// again ts infers T to be {}
const typedBadForced = takeForcedPlainObject(anArray);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment