From 3144671ca4035136c558a107ce61af255ae3e858 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 20 Feb 2024 11:02:52 -0800 Subject: [PATCH] add types --- index.d.ts | 17 +++++++++++++++++ index.js | 17 +++++++++++++++-- package.json | 13 ++++++++++++- test/index.js | 1 + tsconfig.json | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 index.d.ts create mode 100644 tsconfig.json diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..ed2524a --- /dev/null +++ b/index.d.ts @@ -0,0 +1,17 @@ +type TypedArray = + | Int8Array + | Uint8Array + | Uint8ClampedArray + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | Float32Array + | Float64Array + | BigInt64Array + | BigUint64Array; + +declare function typedArrayByteLength(value: TypedArray): number; +declare function typedArrayByteLength(value: unknown): false; + +export = typedArrayByteLength; \ No newline at end of file diff --git a/index.js b/index.js index 501bb15..a1d4e52 100644 --- a/index.js +++ b/index.js @@ -8,10 +8,16 @@ var isTypedArray = require('is-typed-array'); var typedArrays = require('available-typed-arrays')(); +/** @typedef {Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array} TypedArray */ +/** @typedef {import('possible-typed-array-names')[number]} TypedArrayNames */ +/** @typedef {(value: TypedArray) => number} Getter */ + +/** @type {Object.} */ var getters = {}; var oDP = Object.defineProperty; if (gOPD) { + /** @type {Getter} */ var getByteLength = function (x) { return x.byteLength; }; @@ -19,9 +25,12 @@ if (gOPD) { // In Safari 7, Typed Array constructors are typeof object if (typeof global[typedArray] === 'function' || typeof global[typedArray] === 'object') { var Proto = global[typedArray].prototype; + // @ts-expect-error TS doesn't narrow properly inside callbacks var descriptor = gOPD(Proto, 'byteLength'); if (!descriptor && hasProto) { + // @ts-expect-error hush, TS, every object has a dunder proto var superProto = Proto.__proto__; // eslint-disable-line no-proto + // @ts-expect-error TS doesn't narrow properly inside callbacks descriptor = gOPD(superProto, 'byteLength'); } // Opera 12.16 has a magic byteLength data property on instances AND on Proto @@ -30,6 +39,7 @@ if (gOPD) { } else if (oDP) { // this is likely an engine where instances have a magic byteLength data property var arr = new global[typedArray](2); + // @ts-expect-error TS doesn't narrow properly inside callbacks descriptor = gOPD(arr, 'byteLength'); if (descriptor && descriptor.configurable) { oDP(arr, 'length', { value: 3 }); @@ -42,9 +52,10 @@ if (gOPD) { }); } +/** @type {Getter} */ var tryTypedArrays = function tryAllTypedArrays(value) { - var foundByteLength; - forEach(getters, function (getter) { + /** @type {number} */ var foundByteLength; + forEach(getters, /** @type {(getter: Getter) => void} */ function (getter) { if (typeof foundByteLength !== 'number') { try { var byteLength = getter(value); @@ -54,9 +65,11 @@ var tryTypedArrays = function tryAllTypedArrays(value) { } catch (e) {} } }); + // @ts-expect-error TS can't guarantee the callback is invoked sync return foundByteLength; }; +/** @type {import('.')} */ module.exports = function typedArrayByteLength(value) { if (!isTypedArray(value)) { return false; diff --git a/package.json b/package.json index f790cfd..88e12eb 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ ".": "./index.js", "./package.json": "./package.json" }, + "types": "./index.d.ts", "scripts": { "prepack": "npmignore --auto --commentLines=autogenerated", "prepublishOnly": "safe-publish-latest", @@ -14,6 +15,7 @@ "pretest": "npm run lint", "prelint": "evalmd README.md", "lint": "eslint --ext=js,mjs .", + "postlint": "tsc -p .", "tests-only": "nyc tape 'test/**/*.js'", "test": "npm run tests-only", "posttest": "aud --production", @@ -62,6 +64,14 @@ }, "devDependencies": { "@ljharb/eslint-config": "^21.1.0", + "@types/call-bind": "^1.0.5", + "@types/for-each": "^0.3.3", + "@types/gopd": "^1.0.3", + "@types/is-callable": "^1.1.2", + "@types/make-arrow-function": "^1.2.2", + "@types/make-generator-function": "^2.0.3", + "@types/object-inspect": "^1.8.4", + "@types/tape": "^5.6.4", "aud": "^2.0.4", "auto-changelog": "^2.4.0", "available-typed-arrays": "^1.0.7", @@ -75,7 +85,8 @@ "nyc": "^10.3.2", "object-inspect": "^1.13.1", "safe-publish-latest": "^2.0.0", - "tape": "^5.7.5" + "tape": "^5.7.5", + "typescript": "next" }, "engines": { "node": ">= 0.4" diff --git a/test/index.js b/test/index.js index b9a2f3e..5763075 100644 --- a/test/index.js +++ b/test/index.js @@ -11,6 +11,7 @@ var availableTypedArrays = require('available-typed-arrays')(); test('not arrays', function (t) { t.test('non-number/string primitives', function (st) { + // @ts-expect-error st.equal(false, typedArrayByteLength(), 'undefined is not typed array'); st.equal(false, typedArrayByteLength(null), 'null is not typed array'); st.equal(false, typedArrayByteLength(false), 'false is not typed array'); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2002ce5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,49 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + + /* Language and Environment */ + "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + "typeRoots": ["types"], /* Specify multiple folders that act like './node_modules/@types'. */ + "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + + /* JavaScript Support */ + "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + "maxNodeModuleJsDepth": 0, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + "declarationMap": true, /* Create sourcemaps for d.ts files. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + + /* Interop Constraints */ + "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + + /* Completeness */ + //"skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "exclude": [ + "coverage" + ] +}