screepers / typed-screeps

Strong TypeScript declarations for the game Screeps.
MIT License
189 stars 77 forks source link

Refactor find* methods. Part 3/3 : Ban `find<StructureType>()` #237

Open DiamondMofeng opened 1 year ago

DiamondMofeng commented 1 year ago

Part 3 : Ban find<StructureType>()

!!!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

To some point, find<StructureType>() is an explict assertion like as. It does not ensure that you are getting a correct type.

    {
        let towers = creep.pos.findInRange<StructureTower>([] as AnyStructure[], 2, {
            filter: (s)=> s.structureType===STRUCTURE_SPAWN,
        });
        towers[0].attack(creep);    // no error, it's on your own risk
    }

In most cases, you can implement some "safe" "Type Predicate Filter" to avoid mistakes. For example, When filter is just used for structure types:

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

for multiple structure types:

export function includes<T extends U, U>(arr: ReadonlyArray<T>, item: U): item is T {
  return arr.includes(item as T);
}

export function isStructureTypeAmong<T extends AnyStructure["structureType"]>(structureTypes: T[]) {
  return (s: AnyStructure): s is ConcreteStructure<T> => {
    return includes(structureTypes, s.structureType);
  }
}

However, when the conditions become complicated like filtering unfulfilled Spawn,Extension,Tower,..., you can either use an explict assertion, or implement some special "safe" "type predicate filters", like isStoreStructure. It's on your own.