List error (again)

So, im trying to make a baba is you clone. But, i’ve encountered this error. There isnt any documentation or fixes for it online. I hope someone knows how to fix this!

I dont need the key => value array now, but it will come in handy later. Thats why i use it.

PS:
The clone will be “released” when the spritemap is done

    export class tile {
        tx = 0
        ty = 0
        id = "wall"
        constructor(tx: number, ty: number, id: string) {
            this.tx = tx;
            this.ty = ty;
            let temp : string = id;
            if (allTiles[temp]) {

            } else {
                
            }
        }

        clone() {
            return new tile(this.tx, this.tx, this.id)
        }
    }

    export const allTiles = {
        //Entities
        "baba": "baba",

        //Tiles
        "wall": "wall"
        
        //Joiners

    }

Does anyone also know how to have multiple types in a array like this?

I don’t see an array in the code you posted. allTiles in this example is an Object, which is mapping of strings to values (similar to dict in python).

The error here has to do with how TypeScript handles types. By default, TypeScript wants all of your objects to have an interface that specifies all possible keys that can be used to access properties. In this case, you are trying to use a string to get something out of the object, which might be an error because the compiler has no way of knowing if that string is a valid key or not. For example, you could pass “Foo” for the id which is not a valid tile name.

One way to fix this is to simply cast allTiles to the type any. any can have any key, so TypeScript doesn’t mind you using a string like you currently are. The downside of this is that if you actually do make a mistake and use a key you didn’t mean to, the compiler won’t catch the error for you and you’ll have to see it at runtime.

Another way to fix this is to change the type of id to be something that only includes the strings that could actually be used in allTiles. Like this:

namespace baba {
    // This declares a new type that only contains "wall" or "baba"
    export type TileType = keyof typeof allTiles;
    export class tile {
        tx = 0
        ty = 0
        id: tileType = "wall"
        constructor(tx: number, ty: number, id: tileType) {
            this.tx = tx;
            this.ty = ty;
            if (allTiles[id]) {

            } else {

            }
        }

        clone() {
            return new tile(this.tx, this.tx, this.id)
        }
    }

    export const allTiles = {
        //Entities
        "baba": "baba",

        //Tiles
        "wall": "wall"

        //Joiners

    }
}

Oop, i forgot to list the actual error: (sorry) its at this line, when im trying to know if the tileid actually exists in alltiles. Ive changed the alltiles list to use any, this is the error that shows up:
image

if (allTiles[temp]) {
this.id = temp
} else {
this.id = "air"
}
Full code
namespace spriteMap {
    export const tileMapSizePix = 8
    export const tilesXPerScreen = Math.floor(19 / (tileMapSizePix / 8))
    export const tilesYPerScreen = Math.floor(14 / (tileMapSizePix / 8))
    //["tile", new tileLocation, img``]

    export class tileLocation {
        tx = 0
        ty = 0
        constructor(tx: number, ty: number) {
            this.tx = tx;
            this.ty = ty;
        }
    }

    export class tile {
        tx = 0
        ty = 0
        id = "wall"
        defimg = image.create(tileMapSizePix, tileMapSizePix)
        img = image.create(tileMapSizePix, tileMapSizePix)
        constructor(tx: number, ty: number, id: string, img: Image) {
            this.tx = tx;
            this.ty = ty;
            this.id = id;
            this.img = img;
            if (allTiles[id]) {
                this.id == id
            } else {
                this.id == "air" 
            }
        }

        clone() {
            return new tile(this.tx, this.tx, this.id, this.img)
        }
    }

    export let currentTileMap = [
        new spriteMap.tile(8, 8, "wall", img`
            2 2 2 2 2 2 2 2
            2 3 2 2 3 2 2 2
            2 3 3 2 3 2 2 2
            2 2 2 2 2 2 2 2
            3 3 2 2 2 2 2 2
            2 3 2 2 3 2 2 2
            2 3 3 3 3 2 2 2
            2 2 2 2 2 2 2 2
        `)
    ]
    currentTileMap = []
    for (let y = 0; y < tilesYPerScreen; y++) {
        for (let x = 0; x < tilesXPerScreen; x++) {
            currentTileMap.push(new spriteMap.tile(x, y, "air", image.create(0,0)))
        }
    }


    export const allTiles : any = {
        //Entities
        "baba": 1,

        //Tiles
        "wall": "wall",
        "grass": "grass",
        
        //Joiners

    }

    export function getTileAt(tileLocation : spriteMap.tileLocation) {
        let tile = "air"
        return tile
    }

    export function setTileAt() {

    }

    export function isWallAt(tileLocation : spriteMap.tileLocation) {
        let wall = false
        if (tileLocation.tx < 1 || tileLocation.ty < 1) {
            wall = true
        }
        if (tileLocation.tx > tilesXPerScreen || tileLocation.ty > tilesYPerScreen) {
            wall = true
        }
        if (getTileAt(tileLocation) != "air") {
            wall = true
        }
        return wall
    }

    export function moveToTile(sprite: Sprite, tileLocation : spriteMap.tileLocation) {
        if (sprite.data["moving"] == true) {
            return false
        } 
        sprite.data["moving"] = true
        let tileloc = tileLocation//new spriteMap.tileLocation(Math.clamp(1, tilesXPerScreen, tileLocation.tx), Math.clamp(1, tilesYPerScreen, tileLocation.ty))
        for (let i = 0; i < tileMapSizePix; i++) {
            pause(10)
            let x = utilities.lerp(sprite.x, tileloc.tx * tileMapSizePix, i / tileMapSizePix)
            let y = utilities.lerp(sprite.y, tileloc.ty * tileMapSizePix, i / tileMapSizePix)
            sprite.x = x
            sprite.y = y
        }
        sprite.x = tileloc.tx*tileMapSizePix
        sprite.y = tileloc.ty*tileMapSizePix
        sprite.data["moving"] = false
        return !isWallAt(tileLocation)
    }

    export function step(sprite: Sprite, x : number, y : number) {
        let loc = getSpritesTile(sprite)
        loc.tx += x
        loc.ty += y
        if (isWallAt(loc)) {
            return false
        } else {
            moveToTile(sprite, loc)
            return true
        }
    }

    export function getSpritesTile(sprite : Sprite) {
        let x = Math.floor(sprite.x/tileMapSizePix)
        let y = Math.floor(sprite.y / tileMapSizePix)
        return new tileLocation(x,y)
    }

    scene.createRenderable(0, function () {
        for (let i = 0; i < currentTileMap.length; i++) {
            let tile = currentTileMap[i]
            let img1 = tile.img
            let x = tile.tx * tileMapSizePix + (tileMapSizePix / 2)
            let y = tile.ty * tileMapSizePix + (tileMapSizePix/2)
            image.screenImage().drawTransparentImage(img1, x, y)
        }
    })
}

I dont know how to convey it in javascript, let me write it in some pseudocode: (or lua)

table = {"baba" = "you", "wall" = "stop"}
print(table["baba"]) //Puts "you" in the console
print(table["wall"])//Puts out "stop" in the console

if table["baba"] != null then //Checks if the value exists  
end

I fixed it by putting the list before it was referenced anywhere in the code. Didnt think it was so easy

1 Like