FlowJS - gives a type error because it cannot recognize the result of a `typeof` statement











up vote
0
down vote

favorite












The following code results in an error:



type NextItem = string | { [string]: string };

const next: NextItem = 'foo';
const isString = typeof next === 'string';
const toName = isString ? next : Object.keys(next)[0];
^ string [1] is not an object.


but getting rid of the isString variable fixes it:



type NextItem = string | { [string]: string };

const next: NextItem = 'foo';
const toName = typeof next === 'string' ? next : Object.keys(next)[0];


I understand why, but I'm hoping that someone might offer a better solution. I need to reuse the isString variable and would like to keep my code both DRY and SIMPLE (easy to read). So no "clever" (hacky) solutions please.










share|improve this question
























  • Can you use nesting to run all of the string code in its own block, e.g. if (typeof next === 'string') { /* all the string stuff */ } else { /* all the object stuff */ }?
    – loganfsmyth
    yesterday










  • Maybe, that's a tangible solution. It results in more code (longer form of a ternary), but at least it works. Do you mind posting an answer, as that's the only viable solution I have found to this. Thanks!
    – Ryan Wheale
    17 hours ago















up vote
0
down vote

favorite












The following code results in an error:



type NextItem = string | { [string]: string };

const next: NextItem = 'foo';
const isString = typeof next === 'string';
const toName = isString ? next : Object.keys(next)[0];
^ string [1] is not an object.


but getting rid of the isString variable fixes it:



type NextItem = string | { [string]: string };

const next: NextItem = 'foo';
const toName = typeof next === 'string' ? next : Object.keys(next)[0];


I understand why, but I'm hoping that someone might offer a better solution. I need to reuse the isString variable and would like to keep my code both DRY and SIMPLE (easy to read). So no "clever" (hacky) solutions please.










share|improve this question
























  • Can you use nesting to run all of the string code in its own block, e.g. if (typeof next === 'string') { /* all the string stuff */ } else { /* all the object stuff */ }?
    – loganfsmyth
    yesterday










  • Maybe, that's a tangible solution. It results in more code (longer form of a ternary), but at least it works. Do you mind posting an answer, as that's the only viable solution I have found to this. Thanks!
    – Ryan Wheale
    17 hours ago













up vote
0
down vote

favorite









up vote
0
down vote

favorite











The following code results in an error:



type NextItem = string | { [string]: string };

const next: NextItem = 'foo';
const isString = typeof next === 'string';
const toName = isString ? next : Object.keys(next)[0];
^ string [1] is not an object.


but getting rid of the isString variable fixes it:



type NextItem = string | { [string]: string };

const next: NextItem = 'foo';
const toName = typeof next === 'string' ? next : Object.keys(next)[0];


I understand why, but I'm hoping that someone might offer a better solution. I need to reuse the isString variable and would like to keep my code both DRY and SIMPLE (easy to read). So no "clever" (hacky) solutions please.










share|improve this question















The following code results in an error:



type NextItem = string | { [string]: string };

const next: NextItem = 'foo';
const isString = typeof next === 'string';
const toName = isString ? next : Object.keys(next)[0];
^ string [1] is not an object.


but getting rid of the isString variable fixes it:



type NextItem = string | { [string]: string };

const next: NextItem = 'foo';
const toName = typeof next === 'string' ? next : Object.keys(next)[0];


I understand why, but I'm hoping that someone might offer a better solution. I need to reuse the isString variable and would like to keep my code both DRY and SIMPLE (easy to read). So no "clever" (hacky) solutions please.







javascript flowtype






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 17 hours ago

























asked yesterday









Ryan Wheale

12k44567




12k44567












  • Can you use nesting to run all of the string code in its own block, e.g. if (typeof next === 'string') { /* all the string stuff */ } else { /* all the object stuff */ }?
    – loganfsmyth
    yesterday










  • Maybe, that's a tangible solution. It results in more code (longer form of a ternary), but at least it works. Do you mind posting an answer, as that's the only viable solution I have found to this. Thanks!
    – Ryan Wheale
    17 hours ago


















  • Can you use nesting to run all of the string code in its own block, e.g. if (typeof next === 'string') { /* all the string stuff */ } else { /* all the object stuff */ }?
    – loganfsmyth
    yesterday










  • Maybe, that's a tangible solution. It results in more code (longer form of a ternary), but at least it works. Do you mind posting an answer, as that's the only viable solution I have found to this. Thanks!
    – Ryan Wheale
    17 hours ago
















Can you use nesting to run all of the string code in its own block, e.g. if (typeof next === 'string') { /* all the string stuff */ } else { /* all the object stuff */ }?
– loganfsmyth
yesterday




Can you use nesting to run all of the string code in its own block, e.g. if (typeof next === 'string') { /* all the string stuff */ } else { /* all the object stuff */ }?
– loganfsmyth
yesterday












Maybe, that's a tangible solution. It results in more code (longer form of a ternary), but at least it works. Do you mind posting an answer, as that's the only viable solution I have found to this. Thanks!
– Ryan Wheale
17 hours ago




Maybe, that's a tangible solution. It results in more code (longer form of a ternary), but at least it works. Do you mind posting an answer, as that's the only viable solution I have found to this. Thanks!
– Ryan Wheale
17 hours ago












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










Flow's refinements are generally based on direct checks at the time of use, so it will only ever see your isString variable as a boolean with no special meaning.



That leaves you with a few separate options:




  • Tweak the control flow of your code so there are two clear branches, assuming there are many more checks for isString, you can always make a clear branch to handle both cases.


  • Inline the typeof next === 'string' check.



    const toName = typeof next === 'string' ? next : Object.keys(next)[0];



  • Use a predicate function to centralize the isString logic



    function isString(arg: mixed): boolean %checks {
    return typeof arg === "string";
    }

    const toName = isString(next) ? next : Object.keys(next)[0];







share|improve this answer





















  • The utility method (option 3) is the winner. I did not know about predicates in flowtype yet. Thanks!
    – Ryan Wheale
    46 mins ago











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53199219%2fflowjs-gives-a-type-error-because-it-cannot-recognize-the-result-of-a-typeof%23new-answer', 'question_page');
}
);

Post as a guest
































1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










Flow's refinements are generally based on direct checks at the time of use, so it will only ever see your isString variable as a boolean with no special meaning.



That leaves you with a few separate options:




  • Tweak the control flow of your code so there are two clear branches, assuming there are many more checks for isString, you can always make a clear branch to handle both cases.


  • Inline the typeof next === 'string' check.



    const toName = typeof next === 'string' ? next : Object.keys(next)[0];



  • Use a predicate function to centralize the isString logic



    function isString(arg: mixed): boolean %checks {
    return typeof arg === "string";
    }

    const toName = isString(next) ? next : Object.keys(next)[0];







share|improve this answer





















  • The utility method (option 3) is the winner. I did not know about predicates in flowtype yet. Thanks!
    – Ryan Wheale
    46 mins ago















up vote
1
down vote



accepted










Flow's refinements are generally based on direct checks at the time of use, so it will only ever see your isString variable as a boolean with no special meaning.



That leaves you with a few separate options:




  • Tweak the control flow of your code so there are two clear branches, assuming there are many more checks for isString, you can always make a clear branch to handle both cases.


  • Inline the typeof next === 'string' check.



    const toName = typeof next === 'string' ? next : Object.keys(next)[0];



  • Use a predicate function to centralize the isString logic



    function isString(arg: mixed): boolean %checks {
    return typeof arg === "string";
    }

    const toName = isString(next) ? next : Object.keys(next)[0];







share|improve this answer





















  • The utility method (option 3) is the winner. I did not know about predicates in flowtype yet. Thanks!
    – Ryan Wheale
    46 mins ago













up vote
1
down vote



accepted







up vote
1
down vote



accepted






Flow's refinements are generally based on direct checks at the time of use, so it will only ever see your isString variable as a boolean with no special meaning.



That leaves you with a few separate options:




  • Tweak the control flow of your code so there are two clear branches, assuming there are many more checks for isString, you can always make a clear branch to handle both cases.


  • Inline the typeof next === 'string' check.



    const toName = typeof next === 'string' ? next : Object.keys(next)[0];



  • Use a predicate function to centralize the isString logic



    function isString(arg: mixed): boolean %checks {
    return typeof arg === "string";
    }

    const toName = isString(next) ? next : Object.keys(next)[0];







share|improve this answer












Flow's refinements are generally based on direct checks at the time of use, so it will only ever see your isString variable as a boolean with no special meaning.



That leaves you with a few separate options:




  • Tweak the control flow of your code so there are two clear branches, assuming there are many more checks for isString, you can always make a clear branch to handle both cases.


  • Inline the typeof next === 'string' check.



    const toName = typeof next === 'string' ? next : Object.keys(next)[0];



  • Use a predicate function to centralize the isString logic



    function isString(arg: mixed): boolean %checks {
    return typeof arg === "string";
    }

    const toName = isString(next) ? next : Object.keys(next)[0];








share|improve this answer












share|improve this answer



share|improve this answer










answered 17 hours ago









loganfsmyth

99.4k18209181




99.4k18209181












  • The utility method (option 3) is the winner. I did not know about predicates in flowtype yet. Thanks!
    – Ryan Wheale
    46 mins ago


















  • The utility method (option 3) is the winner. I did not know about predicates in flowtype yet. Thanks!
    – Ryan Wheale
    46 mins ago
















The utility method (option 3) is the winner. I did not know about predicates in flowtype yet. Thanks!
– Ryan Wheale
46 mins ago




The utility method (option 3) is the winner. I did not know about predicates in flowtype yet. Thanks!
– Ryan Wheale
46 mins ago


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53199219%2fflowjs-gives-a-type-error-because-it-cannot-recognize-the-result-of-a-typeof%23new-answer', 'question_page');
}
);

Post as a guest




















































































Popular posts from this blog

Schultheiß

Liste der Kulturdenkmale in Wilsdruff

Android Play Services Check