Typeguards
I suppose you've seen the old link. There was a mistake. I use sort method when obj is array
TS Playground link
Although technically, both Array.isArray and function isArray(value){ return Array.isArray(value); } return a boolean their return types are different.
function isArray(value) { // returns type `boolean`
return Array.isArray(value); // returns type `value is any[]`
}
function sort<T>(obj: T | T[]) {
// that's why for TS this is some generic condition, like `obj.id === "42"`
// it has no idea that `isArray` is supposed to be a typeguard.
if (isArray(obj)) {
// so in here it still considers `obj:T | T[]`
// and `T` has no `sort()` method.
obj.sort();
} else ...
}
same for your other "typeguard" isObject.
And you could alias const isArray = Array.isArray; but basically, why? You don't gain anything here.
Sidenote, your implementation of isObject:
If you want to do if(isObject(value) || isFunction(value)) then do that, but don't "hide" the isFunction check inside something called isObject. It's you who will trip over this eventually. Keep these guards as stupidly simple and straightforward as possible.
An example of how your code could look like TS Playground
const isObject = (value: unknown): value is object => typeof value === "object" && value !== null;
function sort<T extends object>(obj: T): T {
if (Array.isArray(obj)) {
obj.sort();
} else if (isObject(obj)) {
// leave me alone TS, I know what I'm doing. Things will be fine
const unsafeObj: any = obj;
for (const [key, value] of Object.entries(obj).sort()) {
delete unsafeObj[key];
unsafeObj[key] = value;
}
}
return obj;
}
const obj = sort({
"foo": "foo",
"bar": "bar",
"baz": "baz",
"asdf": "asdf"
});
console.log(obj);
Warnings: Since Array#sort() is mutating the object, I've implemented the object-sort the same way; that doesn't make it good. Mutating things comes with its own set of problems.
And "sorting" objects like that may be fatal to the performace of any code that has to deal with these objects. If you want ordered key-value pairs, check out Maps
function sort<T>(obj: T | T[])? Or if you know the type already replace T bei the type.obj.sort(..)because it produces error:property sort does not exists on type 'T | T[]'. Of course I can use type assertion, but it looks like workaround:(obj as T[]).sort(..)obj.sort(). The call should look like this:sort(obj). For the same reason, the errorproperty sort does not exists on type 'T | T[]'doesn't make sense, it doesn't match the interface @ThomasRegner provided. Could you please clarify what exactly the interface of your function is and how you call it.obj.sort()inside yoursortfunction. Arrays have asort()-method, other Objects don't. You will have to implement it yourself.