Typescript error - "Element implicitly has an 'any' type because type 'Object' has no index signature"

Anyways, I was working on a project which uses Objects - and a strange error appeared. I’ve encountered it before, but under these circumstances I wasn’t able to get around it.
Here I have a defined object:

const CUBE_VERTICIES = {
    A: new Vertex(0, LENGTH, LENGTH),      //A
    B: new Vertex(LENGTH, LENGTH, LENGTH), //B
    C: new Vertex(LENGTH, 0, LENGTH),      //C
    D: new Vertex(0, 0, LENGTH),           //D
    E: new Vertex(0, LENGTH, 0),           //E
    F: new Vertex(LENGTH, LENGTH, 0),      //F
    G: new Vertex(0, 0, 0),                //G
    H: new Vertex(LENGTH, 0, 0),           //H
}

Within a method which takes in the ‘Object’ type as an argument (the ‘vertices’ variable), I have the following setup:

let vertex
let keys = Object.keys(vertices)
for (let i = 0; i < keys.length; i++) {
    vertex = vertices[keys[i]]
}

After trying to compile, this line returns an error:

vertex = vertices[keys[i]]
Element implicitly has an 'any' type because type 'Object' has no index signature

Does anyone have any idea as to what is going on or a possible solution? This is pretty important, because I’ll have to swap out an object for something else if this error doesn’t get resolved, which will significantly slow my code.

if you change it to

let vertex: Vertex
let keys = Object.keys(vertices)
for (let i = 0; i < keys.length; i++) {
    vertex = vertices[keys[i]]
}

does it possible work?

One thing to note is that object literals are fairly slow in static typescript, particularly on hardware and in comparison to classes – if you were to define a wrapper class like

class CubeVerticies {
    constructor(
        public a: Vertex,
        public b: Vertex,
        ...
    ) { } 
}

on hardware my recollection is that that will run out to something like 10-20x faster field look ups / assignments. Should note that Object.keys is one thing that is not supported on explicit classes currently (https://makecode.com/language#semantic-differences-against-javascript) but if it’s a perf issue you will be much more likely to see gains by taking that as a first step.

2 Likes

You should also consider using a plain array instead of sequential letter keys - I haven’t compared performance, but I think it would make some logic easier, especially if you end up adding more object types.

1 Like

Perhaps there’s a way to define an index signature to the vertices argument?

Hmm, declaring the type still throws the same error… Any other idea as to why this is going wrong?

Hm, not certain, maybe try

vertex = vertices[keys[i]] as Vertex;

or even

vertex = vertices[keys[i]] as any as Vertex;

? It’s a typing error so throwing enough casts at it should eventually fix it :slight_smile:

That said @kwx s point on the data being sequential is good, if you had CubeVertices: Vertex[] you wouldn’t face the same issues – the problem is that indexing into an object literal loses some type information which requires it to be explicitly added back in after the fact

1 Like

Yes, that’s why I thought of adding a ‘label’ property into the Vertex class, so I can look it up inside of a list later. That being said, I’d have to implement something like binary search (alphabetic) to speed up the process, which I don’t really feel like doing. Although, if it comes to it it might be my last resort.

Thanks a lot for the help, but the same error is still showing up :confused:

Hm, sorry about that, without seeing the project I don’t have anything else I can think of immediately :frowning:

That said, if the “c” / “a” label is important then you can always use the fact that characters are just special numbers – e.g. index into the array with "a".charCodeAt(0) - 97 (or console.log("A".charCodeAt(0) - 65)) if capital) and convert from index to label with String.fromCharCode(i + 97) (or, again String.fromCharCode(i + 65) for capital letter

1 Like

That sounds like a great idea! I’ll try it out and see if it solves my problem with the project.

That’s true, I’ll see how it performes. Although this makes it easier to organise (for me) - and hardware performance isn’t at the top of my priorites. (It would be good to make it work first :sweat_smile:)
If I may ask, what kind of projection do you use in your 3d rendering algorithms? I found an easy to implement weak projection alhorithm and I’m currently following it

1 Like

In case it helps, I posted a very high-level overview in [Announcement] MakeCode Arcade Mini Game Jam #4 - Outer Space Jam - #71 by kwx . The projection is pretty much the usual perspective divide apart from using fixed-point math, see the perspectiveTransform(vert: number[]) method in the triangle.ts file. Before doing that, it uses reentrant polygon clipping to ensure that it doesn’t get divide-by-zero errors or problems with behind-the-user surfaces becoming visible.

1 Like

sigh I thought it wouldn’t have to come to this, but I’m stuck. I came to a middle ground, where I made the object into a vertex list, as such:

let CUBE_VERTICES = [
    new Vertex(LENGTH, 0, LENGTH),      //A
    new Vertex(LENGTH, LENGTH, LENGTH), //B
    new Vertex(LENGTH, LENGTH, 0),      //C
    new Vertex(LENGTH, 0, 0),           //D
    new Vertex(0, 0, LENGTH),           //E
    new Vertex(0, LENGTH, LENGTH),      //F
    new Vertex(0, LENGTH, 0),           //G
    new Vertex(0, 0, 0),                //H
]

And I made the point variables (‘A’, ‘B’, ‘C’ and so on) into indexes. This adds a lot of flexiblity, and it was the solution I needed. (see below)

const A = 0
const B = 1
const C = 2
const D = 3
const E = 4
const F = 5
const G = 6
const H = 7

However, there was no time to celebrate, since I ran into another brick wall soon after. MY CUBE ISN’T RENDERING :sob: :sob:
Seriously, I don’t even know is it my code or the vertices I set, but it’s not working, and that’s what matters. I didn’t want to be a leech and get help for EVERYTHING regarding this project, but I’m kind of stumped since this type of project is really new to me.

Here’s the project, break a leg

It is rendering just fine, it’s just in an unusual position since you’re not using the screen center as the projection center. Your offset point is at (20, 20) near the top left corner.

Here’s a quick attempt at changing that:

1 Like

Thanks a lot, I figured it was something to do with offsetting! But, the cube seems kind of stretched, and it’s supposed to be rendered facing forward (see below)


(poorly drawn, close up view of what it should roughly look like)

The main thing is that you need to decide what your coordinate systems are, for example where is the viewer in 3D space, what’s the viewing direction, where is the cube located, and how is it oriented. Assuming that you’ll want to do more complex things such as moving the cube or viewpoint later, you’ll need to start getting that sorted out.

I’ve tweaked your code a bit to make the cube centered on (0, 0, 0) (instead of having a corner at the origin), and added a viewer position. I think this is starting to look more reasonable. If you’re not liking the perspective stretching, try tweaking the focal length. If I’m understanding it right, you’re currently working in pixel units, and your focal length of 20 is very short compared to the screen size (160x120), so you’ll get a fisheye effect for close objects.

1 Like

Wow, thanks a lot - this really helped me!

1 Like