Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow typing of default memory objects #60

Open
seancl opened this issue Jul 28, 2016 · 5 comments
Open

Allow typing of default memory objects #60

seancl opened this issue Jul 28, 2016 · 5 comments

Comments

@seancl
Copy link
Contributor

seancl commented Jul 28, 2016

It seems that currently, you can't apply an interface to members of the built-in Memory objects (such as Memory.creeps) because they're defined in index.d.ts as any. I'd like to propose making a dummy interface for each of the four built-in Memory objects so that a player can then extend those interfaces in their own definition files.

For example, say I make my own interface for a room's memory:

interface MemRoom {
  name: string;
  type: string;
  threat: boolean;
}

If I try to apply it to Memory as follows:

interface Memory {
  rooms: {
    [name: string]: MemRoom;
  };
}

Then with the current typings I will get this error:

error TS2403: Subsequent variable declarations must have the same type.  Variable 'rooms' must be of type '{ [name: string]: any; }', but here has type '{ [name: string]: MemRoom; }'.

If however, there were already a "dummy" interface in the typings called MemRoom:

interface Memory {
    [name: string]: any;
    ...
    rooms: {
        [name: string]: MemRoom;
    };
    ...
}
interface MemRoom {
  [name: string]: any;
}
declare class Room {
  ...
    /**
     * A shorthand to Memory.rooms[room.name]. You can use it for quick access the room’s specific memory data object.
     */
    memory: MemRoom;
  ...
}

Then I could extend MemRoom to give specific types to any variables I want (as I tried to do above). This could be done for all four default Memory objects, and would allow users to type things that they want to store in memory - a huge advantage, I think, since Memory is the biggest source of errors for me these days!

If there is already a way to accomplish this that doesn't require modifying the current screeps declarations, please let me know as I'd be very curious!

@Dessix
Copy link
Collaborator

Dessix commented Sep 14, 2016

Looks viable to me, considering any other member definitions could be easily made to fit the [string]: any hashing strategy. As long as you can show that an optional property of a constrained type still compiles (e.g. testProperty?: number) then I'd say this is ready to go. The only backwards incompatibility would arrive from people using dot accessors for undeclared properties, at which point they'd just have to declare their own extensions to memory and everything would work as expected.

@seancl
Copy link
Contributor Author

seancl commented Sep 15, 2016

Thanks for the input @Dessix. I'm still a little concerned (as mentioned on the PR #61 ) that creating an interface like this will prevent users from being able to save a non-object in a room's memory. This is because the interface is always going to be interpreted as an object.

Although I don't think many people really use it this way, it is in theory perfectly legal to do:

Game.rooms[roomname].memory = 5;

... which TypeScript would reject using this proposal, since there's no way to make the interface MemRoom be a straight number. At least, not that I know of.

@Dessix
Copy link
Collaborator

Dessix commented Sep 15, 2016

It's something that could be done by an alternate idea of a complete lack of definition, allowing the user to add their own interface by a name we utilize, or (maybe?) with an empty definition of an interface. Generally, however, everyone I've seen who has said they were doing that has changed away from it due to the inability to patch additional properties on at runtime during unusual circumstances. I think we're fine to do this as long as it allows basic type safety over memory (which we currently do not have), even if it may not be the optimal long-term solution.

@seancl
Copy link
Contributor Author

seancl commented Sep 17, 2016

I thought of the same idea - leaving an undeclared interface in - but I think that's probably a poor design choice. It would also cause compiler errors on the declarations repo itself.

I think you may be right, however, that type safety in memory is worth the downside of not being able to store a bare value in room/spawn/creep/flag memory. If others agree, then the current PR ought to suffice to do just that.

@bryanbecker
Copy link
Member

I put a PR for this issue here #107

The use case of storing a bare value is such an outlier, I don't think it's worth considering.

And, in the situation that a consumer adamantly wanted to store a single value, they could trivially update their code to conform to the new typing.

Otherwise, you are essentially weighing the cost of:

  • it takes an extra step to store just a literal in memory

vs.

  • Memory is untypable

and then voting for the first case

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants