0

Initially my code was :

type Point = {
    x: number, y: number
};

type Point3D = Point & {
    z: number
}
function printPoint(p: Point | Point3D) {
    log("Point {");
    for (const coordinate in p) {
        log("\t", p[coordinate])
    }
    log("}")
}
printPoint({ x: 1, y: 2, z: 3 })
printPoint({ x: 0.4, y: 4 })

which would cause the error Element implicitly has an 'any' type because expression of type 'string' can't be used to index type .. to which I found the solution here: https://stackoverflow.com/a/69198602/6591533.

There they suggest to use as keyof Type after your index to get rid of the error :

// This works
for (const coordinate in p) {
        log("\t", p[coordinate as keyof Point])
   }
// This does not
for (const coordinate in p) {
        log("\t", p[coordinate as keyof Point3D])
    }
// Neither this
for (const coordinate in p) {
        log("\t", p[coordinate as keyof Point | Point3D])
    }
RequireKeys
  • 466
  • 4
  • 15
  • What's `log()`? Could you make your code a [mre]? – jcalz Jul 22 '22 at 16:34
  • Where is the "intersection type" in this question? `Point | Point3D` is a *union type*, not an intersection type. – jcalz Jul 22 '22 at 16:35
  • Are you just asking how to write `keyof (Point | Point3D)`? That is, is this about syntax? – jcalz Jul 22 '22 at 16:36
  • @jcalz it's just console.log, intersection type is Point3D and yes `keyof (Point | Point3D)` is exactly what I wanted to write – RequireKeys Jul 22 '22 at 16:56
  • Hmm, the question seems to be asking "how to I write `keyof` on the type `Point | Point3D`" which is a union type. I guess `Point3D` is an intersection type, but you could write `interface Point3D extends Point { z: number }` and it changes nothing about your question. Intersection types seem to be a red herring here. What am I missing? – jcalz Jul 22 '22 at 17:05

1 Answers1

1

Use generics and let typescript infer your parameter's type.

type Point = {
    x: number, y: number
};

type Point3D = Point & {
    z: number
}
function printPoint<T>(p: T) {
    console.log("Point {");
    
    for (const coordinate in p) {
        console.log("\t", p[coordinate])
    }

    console.log("}")
}

printPoint({ x: 1, y: 2, z: 3 })
printPoint({ x: 0.4, y: 4 })

Check this here

Update: you can narrow your type like -

function printPoint<T extends Point | Point3D>(p: T) {}
Sajeeb Ahamed
  • 6,070
  • 2
  • 21
  • 30