[英]TypeScript - How to define the function interface that accepts both array and object
I want to write the function that sorts both array and objects.我想编写对数组和对象进行排序的 function。 My attempt is below.
我的尝试如下。
function sort(obj: any) {
if (isArray(obj)) {
// sort as array
} else if (isObject(obj)) {
// sort as object
} else {
// throw error that primitive value can't be sorted
}
}
But it lost the typing at all.但它完全失去了打字。 I tried to use generic parameters but ran into the errors that
obj
has no array methods.我尝试使用泛型参数,但遇到了
obj
没有数组方法的错误。 I tried to use function overloading but ran into the impossibility to distinguish array and objects.我尝试使用 function 重载,但遇到无法区分数组和对象的问题。
Typeguards类型保护
I suppose you've seen the old link.
我想你已经看到了旧链接。 There was a mistake.
有一个错误。 I use sort method when obj is array
当 obj 是数组时我使用排序方法
Although technically, both Array.isArray
and function isArray(value){ return Array.isArray(value); }
虽然从技术上讲,
Array.isArray
和function isArray(value){ return Array.isArray(value); }
function isArray(value){ return Array.isArray(value); }
return a boolean
their return types are different.返回一个
function isArray(value){ return Array.isArray(value); }
boolean
的返回类型不同。
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
.您的其他“类型保护”
isObject
也是如此。
And you could alias const isArray = Array.isArray;
你可以别名
const isArray = Array.isArray;
but basically, why?但基本上,为什么? You don't gain anything here.
你在这里没有任何收获。
Sidenote, your implementation of isObject
:旁注,您的
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
.如果你想这样做
if(isObject(value) || isFunction(value))
那就这样做,但不要“隐藏” isFunction
检查在名为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您的代码可能看起来像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;警告:由于 Array#sort() 正在改变 object,因此我以相同的方式实现了对象排序; 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
如果您想要有序的键值对,请查看Maps
You can specify in your function signature what are the types it's expecting:您可以在 function 签名中指定它所期望的类型:
function sort(obj: object | [])
Then you can first check if obj is an array by using the Array.isArray method.然后可以先使用 Array.isArray 方法检查 obj 是否为数组。
Array.isArray(obj)
If it returns true, you can sort it by using the Array sort method.如果返回 true,则可以使用 Array 排序方法对其进行排序。 To check whether it's an object you can do by:
要检查它是否是 object,您可以执行以下操作:
typeof obj === 'object'&& !(obj instanceof Array)
If you want to sort an object you can do it using the Object.keys method which returns an array of a given object's own enumerable property and the use sort and reduce.如果要对 object 进行排序,可以使用 Object.keys 方法进行排序,该方法返回给定对象自己的可枚举属性的数组,并使用排序和归约。
For example:例如:
Object.keys(obj).sort().reduce(
(obj, key) => {
obj[key] = obj[key];
return obj;
}, {}
);
You could limit your inputs and test only for array您可以限制输入并仅测试数组
function sort(input: object | []) {
if (Array.isArray(input)) {
} else {
}
}
this function only accepts object or array.此 function 仅接受 object 或数组。 but problem is object is a base type and includes other types.
但问题是 object 是基本类型,包括其他类型。
You can use built-in typeguards.您可以使用内置的类型保护。
type A = Array<unknown>
type B = Record<string, unknown>
const isObject = (arg: any): arg is B => !Array.isArray(arg) && arg !== null && typeof arg === 'object';
function sort(obj: any) {
if (Array.isArray(obj)) {
const check = obj; // A
} else if (isObject(obj)) {
const check = obj; //Record<string, unknown>
// sort as object
} else {
const check = obj; // any
}
}
Keep in mind, Array.isArray
is already typeguard.请记住,
Array.isArray
已经是类型保护。
You can use unio type for obj
argument:您可以将 unio 类型用于
obj
参数:
function sort(obj: A): A
function sort(obj: B): B
function sort(obj: A | B) {
if (Array.isArray(obj)) {
const check = obj; // A
return obj
}
if (isObject(obj)) {
const check = obj; //Record<string, unknown>
// sort as object
return obj
}
throw Error('Hello')
}
const x = sort([1, 2]) // A
const y = sort({ a: 1 }) // b
const z = sort(42) // error
function sorting(args: unknown){
if(typeof args === 'object' && !Array.isArray(args)){
// sort as if it is object
}else{
// sort as if it array
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.