Product
Introducing SSO
Streamline your login process and enhance security by enabling Single Sign-On (SSO) on the Socket platform, now available for all customers on the Enterprise plan, supporting 20+ identity providers.
string-literal-list
Advanced tools
Readme
Array of string literals for the runtime.
If you code in typescript, you probably don't need any of this.
The StringList class extends the Array with new methods and supercharges the array interface to infer the string literals.
Methods that mutate the array in place like push, pop, shift, unshift, splice should not be used, there is a strict export that enforce this restriction.
no changes is made to the execution of the methods to minimize side effects and the interface is compatible with the native array to work with library expecting arrays.
an arr.enum
property is available to access the literals similar to the way an enum is accessed in typescript.
then additional methods for string literals and type constructs are implemented:
without(...$)
: filter out the given values, accept string and StringList.withPrefix($)
and withSuffix($)
: add prefix/suffix to all the words.value($)
: similar to enum but throws an error if the value doesn't exists.enum[$]:$
Object is exposed as readonly.withTrim()
: trim all the words.withReplace(search, replacement)
: call the String.prototype.replace on all.withReplaceAll(search, replacement)
: call the String.prototype.replaceAll on all.to"Case"()
methods for case transform, uppercase, lowercase capitalize, etc...toRecordValue/toRecordType
methods to create a type of Record<literal, type | typeof value>
with initial value and builtin or infered types.The array order is preserved in a Tuple to infer the types when possible, some methods like toSorted will cause the new instance to be flagged as unsorted and methods like join() will return a generic string type.
npm install --save string-literal-list
yarn add string-literal-list
import { stringList } from 'string-literal-list';
// Or for a shorter alias
import { sl } from 'string-literal-list';
// Or with a frozen array throwing error on mutation.
// import { stringList } or { sl } from 'string-literal-list/strict.js';
let v = sl('foo', 'bar');
// SL<"["foo","bar"]>;
v.enum.foo;
// "foo"
v.includes(any);
// boolean;
v.withPrefix('prefix.');
// SL<["prefix.foo","prefix.bar"]>
v.withSuffix('.suffix');
// SL<["foo.suffix","bar.suffix"]>
v.concat('zing', 'boom');
// SL<["foo","bar","zing","boom"]>;
v.concatList(sl('zig', 'zag'));
// SL<["foo","bar","zig","zag"]>;
v.value('foo') => 'foo';
v.value('not') => throws;
v.enum['not'] => undefined;
v.withTrim()
// SL<["foo","bar"]>;
v.withReplace('a', 'e')
// SL<["foo","ber"]>;
v.withReplaceAll('o', 'e')
// SL<["fee","bar"]>;
v.without('foo')
// SL<["bar"]>;
import { sl } from 'string-literal-list';
const list = sl('foo', 'bar');
// SL<"foo" | "bar">;
list.enum;
// => { foo: "foo", bar: "bar" };
const prefixed = list.withPrefix('prefix.');
// SL<["prefix.foo","prefix.bar"]>;
const suffixed = list.withSuffix('.suffix');
// SL<["foo.suffix","bar.suffix"]>;
const concat = list.concat('bar', 'foo');
// SL<["foo","bar","bar","foo"]>
const concatList = prefixed.concatList(suffixed);
// SL<["prefix.foo","prefix.bar","foo.suffix","bar.suffix"]>;
concatList.join('::');
// "prefix.foo::prefix.bar::foo.suffix::bar.suffix"
const without = concatList.without('prefix.foo', 'bar.suffix');
const withoutList = concatList.without(sl('prefix.foo', 'bar.suffix'));
// SL<["prefix.bar","foo.suffix"]>;
const bothWay = list.withPrefix('data.').withSuffix('.ext');
// SL<["data.foo.ext",data.bar.ext"]>;
/** @type {any|unknown|'notInTheList'} */
let val;
list.includes(val); // No type error just boolean result.
// similar types fix for indexOf, lastIndexOf, filter, some, every, findIndex and find methods.
// Get a copy of the underlying array -> T[]
const arr = list.mutable(); // => ["foo","bar"]
// access a value in the list
list.value('foo'); // 'foo'
list.value('n'); // throws error
const scored = sl(' has ', 'spaces', ' between ', ' o r', 'in the words')
.withTrim()
.withReplaceAll(' ', '_');
// => SL<["has","spaces","between","o_r","in_the_words"]>
const Upper = sl('foo', 'bar').toUpperCase();
// SL<["FOO","BAR"]>
list.concat()
accept only string as arguments to enable inference.
If a native array is passed the string literals won't be inferred.
list.concatList()
accept 1 list of string literals.
// Inferred
sl('foo', 'bar').concat('zing', 'foo').concatList(sl('gurgle', 'doink'));
// SL<["foo","bar",'zing','foo','gurgle','doink']>
// Not Inferred.
list.concat(['boom', 'bar']);
The results of those methods will result in type loose string[]
or returned U[]
for map / reduce.
See ./types.d.ts and ./StringLiteralList.d.ts for more info on the methods which methods are available and specific type overrides.
The javascript Array interface is not designed to work with constant string literal.
The methods like concat, or includes will expect only the constants as argument, which makes a method like includes() useless, and others build method annoying to type when constructing the constants.
!!MY_LIST_AS_unnecessary_MAP[val]
, but if you want type safety this means no .concat(), no .includes(), no iteration without creating new variables./** @type {((keyof typeof MAP_A) | MAPPED_FROM_MAP_B)[]} */
not solving any issues with the underlying unusable array methods.// Not typed.
const arr = ['foo', 'bar'];
/// const arr: string[]
arr.push('d'); // OK
arr.includes('zing'); // OK
arr.concat(['zing']); // OK
// Typed
const O = {
foo: 'foo',
bar: 'bar',
};
/** @type { (keyof typeof O)[] } */
// @ts-expect-error "Type 'string' is not assignable to type '"foo" | "bar"'
const lit = Object.keys(O);
// or just
/** @type {('foo' | 'bar')[]} */
const lit = new Array('foo', 'bar'); // OK
// const lit: ('foo' | 'bar')[]
// Then
lit.includes('asd');
// Argument of type '"asd"' is not assignable to parameter of type '"foo" | "bar"'.ts(2345)
let val = 'asd';
lit.includes(val);
// Argument of type 'string' is not assignable to parameter of type '"foo" | "bar"'.ts(2345)
lit.concat([val]);
// No overload matches this call.
// Overload 1 of 2, '(...items: ConcatArray<"foo" | "bar">[]): ("foo" | "bar")[]', gave the following error.
// Type 'string' is not assignable to type '"foo" | "bar"'.
// Overload 2 of 2, '(...items: ("foo" | "bar" | ConcatArray<"foo" | "bar">)[]): ("foo" | "bar")[]', gave the following error.
// Argument of type 'string[]' is not assignable to parameter of type '"foo" | "bar" | ConcatArray<"foo" | "bar">'.
// Type 'string[]' is not assignable to type 'ConcatArray<"foo" | "bar">'.
// The types returned by 'slice(...)' are incompatible between these types.
// Type 'string[]' is not assignable to type '("foo" | "bar")[]'.
// Type 'string' is not assignable to type '"foo" | "bar"'.ts(2769)
lit.concat(val);
// No overload matches this call.
// Overload 1 of 2, '(...items: ConcatArray<"foo" | "bar">[]): ("foo" | "bar")[]', gave the following error.
// Argument of type 'string' is not assignable to parameter of type 'ConcatArray<"foo" | "bar">'.
// Overload 2 of 2, '(...items: ("foo" | "bar" | ConcatArray<"foo" | "bar">)[]): ("foo" | "bar")[]', gave the following error.
// Argument of type 'string' is not assignable to parameter of type '"foo" | "bar" | ConcatArray<"foo" | "bar">'.ts(2769)
Thanks to @gustavoguichard and his work on https://github.com/gustavoguichard/string-ts that taught me how to work with string literals.
FAQs
an array for string literal
The npm package string-literal-list receives a total of 152 weekly downloads. As such, string-literal-list popularity was classified as not popular.
We found that string-literal-list demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Streamline your login process and enhance security by enabling Single Sign-On (SSO) on the Socket platform, now available for all customers on the Enterprise plan, supporting 20+ identity providers.
Security News
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Security News
As cyber threats become more autonomous, AI-powered defenses are crucial for businesses to stay ahead of attackers who can exploit software vulnerabilities at scale.