typed-screeps icon indicating copy to clipboard operation
typed-screeps copied to clipboard

Refactor find* methods. Part 2/3 : Ban random cast from results of `find*()`

Open DiamondMofeng opened this issue 2 years ago • 0 comments

Part2: Ban random cast for results of find*()

!!!THIS IS A BREAKING CHANGE!!!

!!!THIS A BREAKING CHANGE!!!

This will not be easily merged. Feel free to give your idea on whether we should apply this to our next major version.

TODO

  • [ ] use overloads to distinguish narrow and non-narrow cases.

This change would ban random cast from results of find*(). If you do not use "type predicate filter", then you have to use as.

For example

{
        {
            // @ts-expect-error
            const towers: StructureTower[] = creep.pos.findInRange(FIND_STRUCTURES, 2, {
                filter: (s) => s.structureType === STRUCTURE_EXTENSION,
            });
            towers[0].attack(creep);
        }
        {
            // @ts-expect-error
            const tower1: StructureTower | null = creep.pos.findClosestByPath([] as AnyStructure[], {
                filter: (s) => s.structureType === STRUCTURE_EXTENSION,
            });
            tower1?.attack(creep);
        }
        {
            // @ts-expect-error
            const tower2: StructureTower | null = creep.pos.findClosestByRange(FIND_STRUCTURES, {
                filter: (s) => s.structureType === STRUCTURE_SPAWN,
            });
            tower2?.attack(creep);
        }
        // using `as` on your own risk
        {
            // $ExpectType StructureTower[]
            const towers: StructureTower[] = creep.pos.findInRange(FIND_STRUCTURES, 2, {
                filter: (s) => s.structureType === STRUCTURE_EXTENSION,
            }) as StructureTower[];
            towers[0].attack(creep);  //no Error. TS trusts you
        }
}

You can use "type predicate filter" to narrow the union type if you do not want to use as

const isStructureType = <T extends StructureConstant>(structureType: T) => {
    return (structure: AnyStructure): structure is ConcreteStructure<T> => {
        return structure.structureType === structureType;
    };
};

    {
        let towers = creep.pos.findInRange([] as AnyStructure[], 2, {
            filter: isStructureType(STRUCTURE_TOWER),
        });
        towers[0].attack(creep);    // ok
    }
    {
        let tower = creep.pos.findClosestByPath([] as AnyStructure[], {
            filter: isStructureType(STRUCTURE_TOWER),
        });
        tower?.attack(creep);    // ok
    }
    {
        let tower = creep.pos.findClosestByRange([] as AnyStructure[], {
            filter: isStructureType(STRUCTURE_TOWER),
        });
        tower?.attack(creep);    // ok
    }


DiamondMofeng avatar Feb 26 '23 12:02 DiamondMofeng