isaacscript-common
Version:
Helper functions and features for IsaacScript mods.
227 lines (226 loc) • 7.8 kB
JavaScript
;
/**
* Consider the following code that uses a number enum:
*
* ```ts
* enum MyEnum {
* Value1,
* }
*
* function asMyEnum(num: number): MyEnum {}
*
* declare const something: unknown;
*
* const foo = something as MyEnum; // no error
* const bar: MyEnum = something; // error
* const baz = asMyEnum(something); // error
* ```
*
* Here, using `as` does not give an error because TypeScript allows you to assert a type to a
* supertype or a subtype. Thus, using `as` to perform a type assertion is not as safe as using a
* variable declaration or a helper function. However, if we use a variable declaration, then the
* `complete/strict-enums` rule is triggered, which requires suppressing the lint rule with a `//
* eslint-disable-next-line`. Thus, the safest and more concise way to do a type assertion is to use
* a helper function.
*
* This file contains helper functions for various number enums that might require type assertions.
* It also contains helper functions for run-time type checks.
*
* @module
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.asCardType = asCardType;
exports.asCollectibleType = asCollectibleType;
exports.asFloat = asFloat;
exports.asInt = asInt;
exports.asLevelStage = asLevelStage;
exports.asNPCState = asNPCState;
exports.asNumber = asNumber;
exports.asPillColor = asPillColor;
exports.asPillEffect = asPillEffect;
exports.asPlayerType = asPlayerType;
exports.asRoomType = asRoomType;
exports.asString = asString;
exports.asTrinketType = asTrinketType;
exports.isBoolean = isBoolean;
exports.isFunction = isFunction;
exports.isInteger = isInteger;
exports.isNumber = isNumber;
exports.isPrimitive = isPrimitive;
exports.isString = isString;
exports.isTable = isTable;
exports.isUserdata = isUserdata;
exports.parseIntSafe = parseIntSafe;
/**
* Helper function to safely cast an `int` to a `CardType`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asCardType(num) {
return num;
}
/**
* Helper function to safely cast an `int` to a `CollectibleType`. (This is better than using the
* `as` TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asCollectibleType(num) {
return num;
}
/**
* Helper function to safely cast an enum to an `int`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asFloat(num) {
return num;
}
/**
* Helper function to safely cast an enum to an `int`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asInt(num) {
return num;
}
/**
* Helper function to safely cast an `int` to a `LevelStage`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asLevelStage(num) {
return num;
}
/**
* Helper function to safely cast an `int` to a `NPCState`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asNPCState(num) {
return num;
}
/**
* Helper function to safely cast an enum to a `number`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asNumber(num) {
return num;
}
/**
* Helper function to safely cast an `int` to a `PillColor`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asPillColor(num) {
return num;
}
/**
* Helper function to safely cast an `int` to a `PillEffect`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asPillEffect(num) {
return num;
}
/**
* Helper function to safely cast an `int` to a `PlayerType`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asPlayerType(num) {
return num;
}
/**
* Helper function to safely cast an `int` to a `RoomType`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asRoomType(num) {
return num;
}
/**
* Helper function to safely cast an enum to a `string`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asString(str) {
return str;
}
/**
* Helper function to safely cast an `int` to a `TrinketType`. (This is better than using the `as`
* TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
*
* This is useful to satisfy the "complete/strict-enums" ESLint rule.
*/
function asTrinketType(num) {
return num;
}
function isBoolean(variable) {
return typeof variable === "boolean";
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
function isFunction(variable) {
return typeof variable === "function";
}
function isInteger(variable) {
if (!isNumber(variable)) {
return false;
}
return variable === Math.floor(variable);
}
function isNumber(variable) {
return typeof variable === "number";
}
/** Helper function to detect if a variable is a boolean, number, or string. */
function isPrimitive(variable) {
const variableType = typeof variable;
return (variableType === "boolean"
|| variableType === "number"
|| variableType === "string");
}
function isString(variable) {
return typeof variable === "string";
}
function isTable(variable) {
// We cannot use `typeof` here since "table" is not a JavaScript type.
return type(variable) === "table";
}
function isUserdata(variable) {
// We cannot use `typeof` here since "userdata" is not a JavaScript type.
return type(variable) === "userdata";
}
/**
* Helper function to convert a string to an integer. Returns undefined if the string is not an
* integer.
*
* Under the hood, this uses the built-in `tonumber` and `math.floor` functions.
*
* This is named `parseIntSafe` in order to match the helper function from `complete-common`.
*/
function parseIntSafe(string) {
if (!isString(string)) {
return undefined;
}
// - The `tonumber` function correctly deals with leading and trailing whitespace.
// - The `tonumber` function correctly deals with a mix of numbers and letters. (e.g. `1a` returns
// undefined.)
const number = tonumber(string);
if (number === undefined) {
return undefined;
}
const flooredNumber = Math.floor(number);
return number === flooredNumber ? flooredNumber : undefined;
}