typescript - Type guard - index of an object - Stack Overflow

Given the function below, I would like to be able to create a type guard for an objectarray, indicatin

Given the function below, I would like to be able to create a type guard for an object/array, indicating whether it has an index or not, whether it's a property or an index. Is this possible in any way?

export function hasIndex(v: unknown, i = 0): v is [typeof keyof i] {
    const p = (v as Record<PropertyKey, unknown>)?.[i];
    return typeof p === 'number' || p instanceof Number;
}

Usage:

export function extractIndex(v: unknown, i = 0) {
    let x = 0;
    if (hasIndex(v, i)) {
        x = v[i]; // <-- e.g.: `v[i]` should be `number`, not `number | undefined`
    }
    return x;
}

SOLVED:

Thanks, guys, @jcalz and @Alexander Nenashev. I really like the way you both think! I hadn’t used as this way in arguments before—it didn’t even cross my mind.

The detail about extractIndex<K extends number> really addressed the point @jcalz mentioned earlier. But honestly, I’m not sure I completely understand. Since the default value is a number, shouldn’t TypeScript infer it? Either way, thanks a lot! I was having a bit of trouble finding this solution, but "once I learned about it, it was so obvious".

{ [i in K]: number }

haha

Given the function below, I would like to be able to create a type guard for an object/array, indicating whether it has an index or not, whether it's a property or an index. Is this possible in any way?

export function hasIndex(v: unknown, i = 0): v is [typeof keyof i] {
    const p = (v as Record<PropertyKey, unknown>)?.[i];
    return typeof p === 'number' || p instanceof Number;
}

Usage:

export function extractIndex(v: unknown, i = 0) {
    let x = 0;
    if (hasIndex(v, i)) {
        x = v[i]; // <-- e.g.: `v[i]` should be `number`, not `number | undefined`
    }
    return x;
}

SOLVED:

Thanks, guys, @jcalz and @Alexander Nenashev. I really like the way you both think! I hadn’t used as this way in arguments before—it didn’t even cross my mind.

The detail about extractIndex<K extends number> really addressed the point @jcalz mentioned earlier. But honestly, I’m not sure I completely understand. Since the default value is a number, shouldn’t TypeScript infer it? Either way, thanks a lot! I was having a bit of trouble finding this solution, but "once I learned about it, it was so obvious".

{ [i in K]: number }

haha

Share Improve this question edited Mar 6 at 20:51 Adrian Miranda asked Mar 5 at 22:42 Adrian MirandaAdrian Miranda 3384 silver badges13 bronze badges 2
  • 1 I don't think you can write a type guard that works for situations where i is just of type number (without necessarily narrowing v to Record<number, number> which is presumably not your intent). You need i to be something specific like 0 or 6 or something generic like K extends number, but for just number it won't do what you want. Even regular control flow analysis has only recently supported this sort of "identical key of some wide type", see microsoft/TypeScript#57847, but it's something you can write as a type predicate. – jcalz Commented Mar 5 at 23:04
  • (see prev comment) I suppose unless someone comes up with something very clever here I might write up an answer saying "this is not possible" with sources, but that's not much fun. – jcalz Commented Mar 5 at 23:05
Add a comment  | 

1 Answer 1

Reset to default 1

My guess when we change i from number to K extends number we are telling TS that we would use a specific number subtype instead of generic number so TS could actually narrow v to a type that contains a specific index with number value. (I don't read @jcalz's comments under questions and learn from answering myself):

Playground

export function hasIndex<K extends number>(v: unknown, i = 0 as K ): v is {[k in K]: number} {
    const p = (v as Record<K, unknown>)?.[i];
    return typeof p === 'number' || p instanceof Number;
}


export function extractIndex<K extends number>(v: unknown, i = 0 as K) {
    let x = 0;
    if (hasIndex(v, i)) {
        x = v[i]; // <-- e.g.: `v[i]` should be `number`, not `number | undefined`
        const y = v[1213]; // error
    }
    return x;
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745004199a4605677.html

相关推荐

  • typescript - Type guard - index of an object - Stack Overflow

    Given the function below, I would like to be able to create a type guard for an objectarray, indicatin

    21小时前
    30

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信