最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Flow allow concatenation with object.entries and string - Stack Overflow

programmeradmin1浏览0评论

I have a type like this:

type Cool = {
    [key: string]: number
}

Now, let's say I have an object with that type:

let my: Cool = {
    "asdf": 1,
    "jkl": 2
}

When I run Object.entries(my), I get [["asdf", 1], ["jkl", 2]]. This seems normal. However, I want to bine each key to form a string, like this:

let mystring = "";
Object.entries(my).forEach(entry => {
    mystring = entry[1] + mystring;
});

I would expect that mystring is equal to "jklasdf" and it is. However, I get a flow error on the mystring = ... line. The error states:

Cannot cast Object.entries(...)[0][1] to string because mixed [1] is inpatible with string

Any thoughts on how to fix this? Thanks!

I have a type like this:

type Cool = {
    [key: string]: number
}

Now, let's say I have an object with that type:

let my: Cool = {
    "asdf": 1,
    "jkl": 2
}

When I run Object.entries(my), I get [["asdf", 1], ["jkl", 2]]. This seems normal. However, I want to bine each key to form a string, like this:

let mystring = "";
Object.entries(my).forEach(entry => {
    mystring = entry[1] + mystring;
});

I would expect that mystring is equal to "jklasdf" and it is. However, I get a flow error on the mystring = ... line. The error states:

Cannot cast Object.entries(...)[0][1] to string because mixed [1] is inpatible with string

Any thoughts on how to fix this? Thanks!

Share Improve this question edited Jun 9, 2019 at 22:09 Ryan Z asked Jun 6, 2019 at 21:49 Ryan ZRyan Z 2,7852 gold badges10 silver badges21 bronze badges 4
  • 1 Weird, when I input your code in flow/try, it says there are no errors. – BoltKey Commented Jun 6, 2019 at 22:04
  • According to the core typings from Flow, the result of Object.entries is an Array<[string, mixed]> so accessing entry[0] should yield a string (reference). Maybe you're trying to access entry[1] (which would have type mixed)? – user11307804 Commented Jun 7, 2019 at 14:20
  • Thanks @user11307804 ! I am accessing entry[1] in fact! – Ryan Z Commented Jun 9, 2019 at 22:08
  • @RyanZ, see github./facebook/flow/issues/2221 if you're still having trouble with this. – user11307804 Commented Jun 10, 2019 at 14:16
Add a ment  | 

2 Answers 2

Reset to default 7 +100

Object.entries is typed as:

static entries(object: $NotNullOrVoid): Array<[string, mixed]>

And when you try to use a value of a mixed type you must first figure out what the actual type is or you’ll end up with an error, so you can use Flow's type refinement :

Object.entries(my).forEach(entry => {
  if (typeof entry[1] === 'number') {
    mystring = entry[1] + mystring;
  }
});

You could also just cast entry[1]:

Object.entries(my).forEach(entry => {
  mystring = Number(entry[1]) + mystring;
});

or add type to entry like this entry: [string, any] but note that using any is pletely unsafe, and should be avoided whenever possible.

DEMO

Your problem is with the algorithm, not the types.

First of all, if you want mystring to equal "jklasdf", then you need to access the first index [0] like this entry[0], because the first element in the array is the key of object, if that's what you're looking for.

https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries

The Object.entries() method returns an array of a given object's own enumerable string-keyed property [key, value] pairs...

So your code -regardless of the types- should be:

let my = {
    "asdf": 1,
    "jkl": 2
}

let mystring = "";
Object.entries(my).forEach(entry => {
    mystring = entry[0] + mystring; // access the 0th element
});

console.log(mystring);
// jklasdf

So, now your flow types have no problem at all. https://flow/try/#0C4TwDgpgBAwg9nANlAvFA3gKCjqBtAawhAC4oBnYAJwEsA7AcwF0y6BXAWwCMIrMBfTJkQRgUDqVgJkaLLigAiAIbkAJgDMFZAIwAabLgUArAoi1QATAKEixEyrUapFCgNyYA8lyMQAxsAA6CDpqGghyAAoJAEoA9TgqAFElXwALCODqEFQAPgwDHHtQpzRMqhA8AAYmKABqcRAHegZ3fmjXIA

But, if I would remend a more readable code to achieve the same result:

let my = {
    "asdf": 1,
    "jkl": 2
}

let mystring = "";
   
for (const [key, value] of Object.entries(my)) {
    mystring = [key, mystring].join('')
}

console.log(mystring);
// jklasdf

Or using Array.prototype.reduce:

let my = {
    "asdf": 1,
    "jkl": 2
}

const mystring = Object.entries(my)
                    .reduce((result, [key, value]) => {
                        return result = [key, result].join('');
                    }, "");

console.log(mystring);
// jklasdf

发布评论

评论列表(0)

  1. 暂无评论