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

Union types, guard, why error in typescript? - Stack Overflow

programmeradmin1浏览0评论

Have this code

type IUnionType = IMulti | ISingle;
    function isMulti(q: IUnionType): q is IMulti {
        return 'ans' in q;
    }
    
    //this code is no errors
    if (isMulti(o.q[0])) {
                o.q[0].ans= []; // this case TS know that o.q[0] is IMulti
    }
    //this code have error Property 'ans' does not exist on type 'IUnionType'.
      Property 'ans' does not exist on type 'ISingle'
    var z = 1;
    if (isMulti(o.q[z])) {
                o.q[z].ans= []; // this case TS DONOT KNOW that o.q[0] is IMulti
    }

Difference between code is that i access o.q by index in var z.

Why is have TS error in second case? same error i have if i iterate o.q in for loop

Have this code

type IUnionType = IMulti | ISingle;
    function isMulti(q: IUnionType): q is IMulti {
        return 'ans' in q;
    }
    
    //this code is no errors
    if (isMulti(o.q[0])) {
                o.q[0].ans= []; // this case TS know that o.q[0] is IMulti
    }
    //this code have error Property 'ans' does not exist on type 'IUnionType'.
      Property 'ans' does not exist on type 'ISingle'
    var z = 1;
    if (isMulti(o.q[z])) {
                o.q[z].ans= []; // this case TS DONOT KNOW that o.q[0] is IMulti
    }

Difference between code is that i access o.q by index in var z.

Why is have TS error in second case? same error i have if i iterate o.q in for loop

Share Improve this question asked yesterday Andrew MAndrew M 173 bronze badges 5
  • please provide a reproducible example here: typescriptlang.org/play – Alexander Nenashev Commented yesterday
  • 1 The minimal reproducible example needs to be here as plaintext. A link is nice but insufficient on its own. Please declare anything we need to work on this, such as whatever IMulti and ISingle are – jcalz Commented yesterday
  • Here is playground typescriptlang.org/play/?#code/… – Andrew M Commented yesterday
  • 2 • Please read my comment again: Please include all relevant code as plaintext in the question itself. Links to code are not sufficient to be a minimal reproducible example. Until the code is included here as plaintext, the question risks being closed as needing debugging details. • The relevant feature is ms/TS#57847. TS knows 0 is constant. With var z, TS doesn't try to track it because var scope is weird. You can make z a const or a let for it to work. Does that fully address the q? If so I'll write an a. – jcalz Commented yesterday
  • Since variables declared with the var keyword are hoisted to the top of their scope, in this case the function scope and Typescript doesn't assume that z is constant. It treats o.q[z] as an indexed access expression with an unknown, potentially changing key and doesn't apply narrowing. This should be fixed with the let keyword – Oluwafemi Sule Commented 12 hours ago
Add a comment  | 

1 Answer 1

Reset to default 0

TS doesn't support scoping of var in narrowing, just use let. Overall using var is a very bad idea nowadays, very bug prone, for example no conflict of variables with the same name. FOr loops use an intermediate variable if needed:

function zzz(o: {q:IUnionType[]}){
    let idx = 1;
    if (isMulti(o.q[idx])) {
        o.q[idx].ans= []; 
    }

    for(let i=0;i<o.q.length;i++){
        const item = o.q[i];
        if (isMulti(item)) {
            item.ans= []; // this case TS know that o.q[0] is IMulti
        }
    }

    for(const item of o.q){
        if (isMulti(item)) {
            item.ans= []; // this case TS know that o.q[0] is IMulti
        }
    }
}
发布评论

评论列表(0)

  1. 暂无评论