@avstantso/ts 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +203 -16
- package/dist/_global/string.d.ts +25 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -73,22 +73,189 @@ const flattened = TS.flat({ a: 1, b: { c: 2 } }); // { a: 1, c: 2 }
|
|
|
73
73
|
|
|
74
74
|
The `@avstantso/ts` package provides a comprehensive suite of type-level utilities organized into the following namespaces:
|
|
75
75
|
|
|
76
|
-
- [TS.Extends](#tsextends)
|
|
77
|
-
- [TS.Increment / TS.Decrement](#tsincrement--tsdecrement)
|
|
78
|
-
- [TS.
|
|
79
|
-
- [TS.
|
|
80
|
-
- [TS.
|
|
81
|
-
- [TS.
|
|
82
|
-
- [TS.
|
|
83
|
-
- [TS.
|
|
84
|
-
- [TS.
|
|
85
|
-
- [
|
|
86
|
-
- [TS.
|
|
87
|
-
-
|
|
88
|
-
- [TS.
|
|
89
|
-
- [TS.
|
|
90
|
-
- [TS.
|
|
91
|
-
- [TS
|
|
76
|
+
- [TS.Extends](#tsextends) — Type extension checking
|
|
77
|
+
- [TS.Increment / TS.Decrement](#tsincrement--tsdecrement) — Numeric type arithmetic
|
|
78
|
+
- [TS.ArrN / TS.ArrM](#tsarrn-and-tsarrm) — Array type constraints
|
|
79
|
+
- [TS.Func](#tsfunc) — Function type utilities
|
|
80
|
+
- [TS.Func.Nested](#tsfuncnesteddepth-r-p) — Nested function type
|
|
81
|
+
- [TS.Union](#tsunion) — Union type manipulation
|
|
82
|
+
- [TS.Union.ToIntersection](#tsuniontointersectionu) — Union → intersection
|
|
83
|
+
- [TS.Union.Pop](#tsunionpopu) — Pop last from union
|
|
84
|
+
- [TS.Union.ToTuple](#tsuniontotupleu) — Union → tuple
|
|
85
|
+
- [TS.Union.IsUnion](#tsunionisuniont-iftrue--true-iffalse--false) — Test if union
|
|
86
|
+
- [TS.Array](#tsarray) — Array type utilities
|
|
87
|
+
- Creation
|
|
88
|
+
- [TS.Array.Create](#tsarraycreatel-item) — Create array of length
|
|
89
|
+
- [TS.Array.Create.Optional](#tsarraycreateoptionald-item) — Create optional array
|
|
90
|
+
- [TS.Array.Numbers](#tsarraynumbersl) — Numeric literals array
|
|
91
|
+
- [TS.Array.Letters](#tsarraylettersl) — Letters array
|
|
92
|
+
- Analysis
|
|
93
|
+
- [TS.Array.Length](#tsarraylength-tarr) — Array length
|
|
94
|
+
- [TS.Array.Length.IfExeeded](#tsarraylengthifexeededtarr-n-iftrue--true-iffalse--false) — Test length exceeded
|
|
95
|
+
- Search
|
|
96
|
+
- [TS.Array.IndexOf](#tsarrayindexoftarr-item-i--0) — Find index of item
|
|
97
|
+
- [TS.Array.IfHasItem](#tsarrayifhasitemtarr-item-iftrue--true-iffalse--false) — Test has item
|
|
98
|
+
- [TS.Array.IfEach](#tsarrayifeachtarr-item-iftrue--true-iffalse--false) — Test each item
|
|
99
|
+
- [TS.Array.CountOf](#tsarraycountoftarr-item) — Count matching items
|
|
100
|
+
- Transformation
|
|
101
|
+
- [TS.Array.AddUnique](#tsarrayadduniquetarr-item) — Add unique item
|
|
102
|
+
- [TS.Array.MergeUnique](#tsarraymergeuniquetarr1-tarr2) — Merge without duplicates
|
|
103
|
+
- [TS.Array.Filter](#tsarrayfiltertarr-tfilter--undefined) — Filter items
|
|
104
|
+
- [TS.Array.Filter.Unique](#tsarrayfilteruniquetarr) — Remove duplicates
|
|
105
|
+
- [TS.Array.Sub](#tsarraysubtarr-start-end) — Sub-array
|
|
106
|
+
- [TS.Array.Remove](#tsarrayremovetarr-start-end) — Remove section
|
|
107
|
+
- [TS.Array.Reverse](#tsarrayreversetarr) — Reverse array
|
|
108
|
+
- [TS.Array.Join](#tsarrayjointarr) — Join to string
|
|
109
|
+
- [TS.Array.Cast](#tsarraycasttarr-item--any) — Cast items to type
|
|
110
|
+
- Map / Record
|
|
111
|
+
- [TS.Array.ToKey](#tsarraytokeytarr) — Array → key union
|
|
112
|
+
- [TS.Array.ToKey2Key](#tsarraytokey2keytarr) — Key-to-key record
|
|
113
|
+
- [TS.Array.ToRecord](#tsarraytorecordtarr-t) — Array → record
|
|
114
|
+
- [TS.Array.KeyValueMapFrom](#tsarraykeyvaluemapfromkeys-firstvalue--0) — Key-value map
|
|
115
|
+
- [TS.Array.ValueKeyMapFrom](#tsarrayvaluekeymapfromkeys-firstvalue--0) — Value-key map
|
|
116
|
+
- Min / Max / Sort
|
|
117
|
+
- [TS.Array.Min](#tsarraymintarr) — Find minimum
|
|
118
|
+
- [TS.Array.Min.Index](#tsarrayminindextarr) — Find minimum index
|
|
119
|
+
- [TS.Array.Max](#tsarraymaxtarr) — Find maximum
|
|
120
|
+
- [TS.Array.Max.Index](#tsarraymaxindextarr) — Find maximum index
|
|
121
|
+
- [TS.Array.Sort](#tsarraysorttarr-asc--true) — Sort array
|
|
122
|
+
- [TS.Array.Sort.Pair](#tsarraysortpairk) — Pair for key-based sorting
|
|
123
|
+
- [TS.Array.Sort.Desc](#tsarraysortdesctarr) — Sort descending
|
|
124
|
+
- Runtime
|
|
125
|
+
- [TS.Array.ToKey2Key()](#tsarraytokey2keyaarr-a) — Create key-to-key record (runtime)
|
|
126
|
+
- [TS.ASCII](#tsascii) — ASCII character types and maps
|
|
127
|
+
- Letters
|
|
128
|
+
- [TS.ASCII.Letters](#tsasciilettersisuppertrue) — Letter array by case
|
|
129
|
+
- [TS.ASCII.Letters.Upper](#tsasciilettersupper) / [.Lower](#tsasciiletterslower) — Upper/lowercase letter arrays
|
|
130
|
+
- [TS.ASCII.Letter](#tsasciiletter) — Letter union by case
|
|
131
|
+
- [TS.ASCII.Letter.Upper](#tsasciiletterupper) / [.Lower](#tsasciiletterlower) — Upper/lowercase letter unions
|
|
132
|
+
- Character Arrays
|
|
133
|
+
- [TS.ASCII](#tsascii-2) — All ASCII characters
|
|
134
|
+
- [TS.ASCII.Control](#tsasciicontrol) / [.Printable](#tsasciiprintable) / [.Extended](#tsasciiextended) — Character subsets
|
|
135
|
+
- Maps
|
|
136
|
+
- [TS.ASCII.Map](#tsasciimap) — Character → code map
|
|
137
|
+
- [TS.ASCII.Map.Control](#tsasciimapcontrol) / [.Printable](#tsasciimapprintable) / [.Extended](#tsasciimapextended) — Subset maps
|
|
138
|
+
- [TS.ASCII.Code](#tsasciicode) — Character → code lookup
|
|
139
|
+
- [TS.ASCII.Character](#tsasciicharacter) — All ASCII characters union
|
|
140
|
+
- [TS.Comparisons](#tscomparisons) — Type-level comparisons
|
|
141
|
+
- [TS.Comparisons.LT](#tscomparisonslt) — Less than
|
|
142
|
+
- [TS.Comparisons.LTE](#tscomparisonslte) — Less than or equal
|
|
143
|
+
- [TS.Comparisons.GT](#tscomparisonsgt) — Greater than
|
|
144
|
+
- [TS.Comparisons.GTE](#tscomparisonsgte) — Greater than or equal
|
|
145
|
+
- [TS.String](#tsstring) — String type manipulation
|
|
146
|
+
- [TS.String\<T, D\>](#tsstring-1) — Cast to string literal
|
|
147
|
+
- [TS.String.Possible](#tsstringpossible) — Convertible types
|
|
148
|
+
- [TS.String.Pattern](#tsstringpattern) — Regex pattern shortcuts
|
|
149
|
+
- Analysis
|
|
150
|
+
- [TS.String.Length](#tsstringlength) — String length
|
|
151
|
+
- [TS.String.IsLengthBetween](#tsstringislengthbetween) — Length in range
|
|
152
|
+
- [TS.String.SplitToChars](#tsstringsplittochars) — Split to characters
|
|
153
|
+
- [TS.String.Split](#tsstringsplits-separator) — Split by separator
|
|
154
|
+
- Manipulation
|
|
155
|
+
- [TS.String.Repeat](#tsstringrepeat) — Repeat N times
|
|
156
|
+
- [TS.String.Includes](#tsstringincludes) — Test includes pattern
|
|
157
|
+
- [TS.String.IndexOf](#tsstringindexof) — Find pattern index
|
|
158
|
+
- [TS.String.Replace](#tsstringreplace) — Replace matches
|
|
159
|
+
- [TS.String.Trim](#tsstringtrim) — Trim whitespace
|
|
160
|
+
- [TS.String.Trim.Start](#tsstringtrimstart) / [.End](#tsstringtrimend) — Trim start/end
|
|
161
|
+
- Case Conversion
|
|
162
|
+
- [TS.String.Case](#tsstringcasetype-s-r) — Generic case conversion
|
|
163
|
+
- [TS.String.Case.Camel](#tsstringcasecamels-r--removes) — camelCase
|
|
164
|
+
- [TS.String.Case.Pascal](#tsstringcasepascals-r--removes) — PascalCase
|
|
165
|
+
- [TS.String.Case.Snake](#tsstringcasesnakes-r--removes) — snake_case
|
|
166
|
+
- [TS.String.Case.Snake.Up](#tsstringcasesnakeups-r--removes) — UPPER_SNAKE_CASE
|
|
167
|
+
- [TS.String.Case.Kebab](#tsstringcasekebabs-r--removes) — kebab-case
|
|
168
|
+
- [TS.String.Case.Settings.Removes](#tsstringcasesettingsremoves) — Removal characters
|
|
169
|
+
- [TS.String.Case.Settings.Removes.Map](#tsstringcasesettingsremovesmap) — Extensible removal map
|
|
170
|
+
- [TS.Structure](#tsstructure) — Object structure utilities
|
|
171
|
+
- Test
|
|
172
|
+
- [TS.Structure.IfStructure](#tsstructureifstructuret-iftrue--true-iffalse--false) — Test is structure
|
|
173
|
+
- [TS.Structure](#tsstructuret) — Structure constraint
|
|
174
|
+
- [TS.Structure.Wildcard](#tsstructurewildcard) / [.MapOfNotRules](#tsstructuremapofnotrules) / [.NotRules](#tsstructurenotrules) — Rules
|
|
175
|
+
- Conversion
|
|
176
|
+
- [TS.Structure.ToKeysArray](#tsstructuretokenysarrayo) — Keys tuple
|
|
177
|
+
- [TS.Structure.ToValuesArray](#tsstructuretovaluesarrayo) — Values tuple
|
|
178
|
+
- [TS.Structure.ToEntriesArray](#tsstructuretoentriesarrayo) — Entries tuple
|
|
179
|
+
- Manipulation
|
|
180
|
+
- [TS.Structure.Separate](#tsstructureseparatet) — Separate plain/structural
|
|
181
|
+
- [TS.Structure.Reverse](#tsstructurereverse) — Reverse to value-key map
|
|
182
|
+
- [TS.Structure.Split](#tsstructuresplito) — Split to single-field objects
|
|
183
|
+
- [TS.Structure.Combine](#tsstructurecombinea) — Combine objects
|
|
184
|
+
- Runtime
|
|
185
|
+
- [TS.Structure.is()](#tsstructureis) — Test is structure (runtime)
|
|
186
|
+
- [TS.Structure.keyByValue()](#tsstructurekeybyvalue) — Find key by value (runtime)
|
|
187
|
+
- [TS.Structure.reverse()](#tsstructurereverse-1) — Reverse structure (runtime)
|
|
188
|
+
- [Object Constructor Extensions](#object-constructor-extensions) — Typed Object.keys/values/entries
|
|
189
|
+
- [Object.keysEx](#objectkeyso)
|
|
190
|
+
- [Object.valuesEx](#objectvaluesexo)
|
|
191
|
+
- [Object.entriesEx](#objectentriesexo)
|
|
192
|
+
- [TS.Boolean](#tsboolean) — Boolean logic types
|
|
193
|
+
- [TS.If](#tsifcondition-iftrue--true-iffalse--false) — Conditional
|
|
194
|
+
- [TS.If.And](#tsifandconditions-iftrue--true-iffalse--false) — Logical AND
|
|
195
|
+
- [TS.If.Or](#tsiforconditions-iftrue--true-iffalse--false) — Logical OR
|
|
196
|
+
- [TS.If.Xor](#tsifxorconditions-iftrue--true-iffalse--false) — Logical XOR
|
|
197
|
+
- [TS.Numeric](#tsnumeric) — Numeric literal utilities
|
|
198
|
+
- Domain-Independent
|
|
199
|
+
- [TS.Numeric.IsPositive](#tsnumericispositive) / [.IsNegative](#tsnumericisnegative) — Sign tests
|
|
200
|
+
- [TS.Numeric.Positive.ToNegative](#tsnumericpositivetonegative) / [Numeric.Negative.ToPositive](#tsnumericnegativetopositive) — Sign conversion
|
|
201
|
+
- [TS.Numeric.Sign](#tsnumericsign) — Get sign
|
|
202
|
+
- [TS.Numeric.Digits](#tsnumericdigits) — Digit characters
|
|
203
|
+
- [TS.Numeric.Digits.Map](#tsnumericdigitsmap) / [.IsOdd](#tsnumericdigitsisodd) — Digit maps
|
|
204
|
+
- [TS.Numeric.Digits.Hex](#tsnumericdigitshex) / [.Hex.Map](#tsnumericdigitshexmap) — Hexadecimal digits
|
|
205
|
+
- [TS.Numeric.IsOdd](#tsnumericisodd) / [.IsEven](#tsnumericiseven) — Parity tests
|
|
206
|
+
- [TS.Numeric.IsNumber](#tsnumericisnumber) — String → number test
|
|
207
|
+
- [TS.Numeric.Parse](#tsnumericparse) — String → number literal
|
|
208
|
+
- Domain
|
|
209
|
+
- [TS.Numeric.Domain.Positive](#tsnumericdomainpositive) / [.Negative](#tsnumericdomainnegative) — Numeric ranges
|
|
210
|
+
- [TS.Numeric.Domain.Increment](#tsnumericdomainincrement) / [.Decrement](#tsnumericdomaindecrement) — Full-domain inc/dec
|
|
211
|
+
- Math
|
|
212
|
+
- [TS.Numeric.Abs](#tsnumericabsn) — Absolute value
|
|
213
|
+
- [TS.Numeric.Invert](#tsnumericinvertn) — Invert sign
|
|
214
|
+
- [TS.Numeric.Summ](#tsnumericsummx-y) — Addition
|
|
215
|
+
- [TS.Numeric.Diff](#tsnumericdiffx-y) — Subtraction
|
|
216
|
+
- [TS.Numeric.Multiply](#tsnumericmultiplyx-y) — Multiplication
|
|
217
|
+
- [TS.Numeric.Div](#tsnumericdivx-y) — Division
|
|
218
|
+
- [TS.Numeric.Power](#tsnumericpowerx-e) — Exponentiation
|
|
219
|
+
- [TS.Literal](#tsliteral) — Type literal definitions
|
|
220
|
+
- [TS.Literal](#tsliteral-1) — Available literals union
|
|
221
|
+
- [TS.Literal.Map](#tsliteralmap) — Literal → type map
|
|
222
|
+
- [TS.Literal.NumberLike](#tsliteralnumberlike) / [.IsNumberLike](#tsliteralisnumberlike) — Number-like literals
|
|
223
|
+
- [TS.Literal.StringLike](#tsliteralstringlike) / [.IsStringLike](#tsliteralisstringlike) — String-like literals
|
|
224
|
+
- [TS.Literal.List](#tsliterallist) — Literals array
|
|
225
|
+
- [TS.Literal.Key2KeyRec](#tsliteralkey2keyrec) — Key-to-key record
|
|
226
|
+
- Runtime
|
|
227
|
+
- [TS.Literal.List](#tsliterallist-1) — Literals array (runtime)
|
|
228
|
+
- [TS.Literal.Empty()](#tsliteralemptytype) — Get empty value
|
|
229
|
+
- [TS.Literal.IsValue()](#tsliteralisvaluetype-value) — Type guard
|
|
230
|
+
- [TS.Literal._Register()](#tsliteral_registerliteral-empty) — Register custom literal
|
|
231
|
+
- [TS.Type](#tstype) — Type manipulation utilities
|
|
232
|
+
- [TS.Type](#tstype-1) — Available types union
|
|
233
|
+
- [TS.Type.Not](#tstypenotfunction) — Exclude types
|
|
234
|
+
- [TS.Type.Def](#tstypedef) — Type definition structure
|
|
235
|
+
- [TS.Type.KeyDef](#tstypekeydef) — Keyed type definition
|
|
236
|
+
- [TS.Type.KLD](#tstypekld) — Key-literal-default array
|
|
237
|
+
- [TS.Type.Union](#tstypeunion) — Type union with literal
|
|
238
|
+
- Runtime
|
|
239
|
+
- [TS.Type.KeyDef()](#tstypekeydefkey-type) — Create keyed def (runtime)
|
|
240
|
+
- [TS.Type.KLD()](#tstypekldkey-type-def) — Create KLD (runtime)
|
|
241
|
+
- [TS.Resolve](#tsresolve) — Type literal resolution
|
|
242
|
+
- [TS Utility Types](#ts-utility-types) — Miscellaneous utility types
|
|
243
|
+
- [TS.Alt](#tsaltt) — Alternative fields
|
|
244
|
+
- [TS.Flat](#tsflatt-depth--1) — Flatten structure
|
|
245
|
+
- [TS.IfDef](#tsifdef) / [TS.IfDefKey](#tsifdefkey) — Defined selection
|
|
246
|
+
- [TS.Opaque](#tsopaquetypemeta-t) — Opaque/nominal types
|
|
247
|
+
- [TS.Options](#tsoptionstypemap-tdefaults) — Options with defaults
|
|
248
|
+
- Override
|
|
249
|
+
- [TS.Override](#tsoverridetbase-textended-toptional--false) — Override properties
|
|
250
|
+
- [TS.IfIsOverrided](#tsifisoverrided) / [.IfIsOverridedKey](#tsifisoverridedkey) — Test overridden
|
|
251
|
+
- [TS.IfNotOverrided](#tsifnotoverrided) / [.IfNotOverridedKey](#tsifnotoverridedkey) — Select if not overridden
|
|
252
|
+
- [TS.OverrideIfNot](#tsoverrideifnot) — Conditional override
|
|
253
|
+
- [TS.ReplaceKey](#tsreplacekey) / [TS.ReplaceKeyOpt](#tsreplacekeyopt) — Replace key type
|
|
254
|
+
- [TS.RequiredKeys](#tsrequiredkeys) / [TS.OptionalKeys](#tsoptionalkeys) — Key extraction
|
|
255
|
+
- [TS.Merge](#tsmerge) / [TS.Merge.Fields](#tsmergefields) — Type merging
|
|
256
|
+
- Runtime
|
|
257
|
+
- [TS.isKey()](#tsiskeyk-extends-avstandsotskey) — Key type guard
|
|
258
|
+
- [TS.flat()](#tsflatstructure-depth--1) — Flatten structure (runtime)
|
|
92
259
|
|
|
93
260
|
---
|
|
94
261
|
|
|
@@ -960,6 +1127,26 @@ type Single = TS.String.SplitToChars<'A'>; // ['A']
|
|
|
960
1127
|
type Multiple = TS.String.SplitToChars<'AB'>; // ['A', 'B']
|
|
961
1128
|
```
|
|
962
1129
|
|
|
1130
|
+
#### `TS.String.Split<S, Separator>`
|
|
1131
|
+
|
|
1132
|
+
Split string literal into substrings array by `Separator`.
|
|
1133
|
+
|
|
1134
|
+
**Type Parameters:**
|
|
1135
|
+
- `S` - String literal to split
|
|
1136
|
+
- `Separator` - ASCII character to split by
|
|
1137
|
+
|
|
1138
|
+
**Returns:** Array of string literal substrings
|
|
1139
|
+
|
|
1140
|
+
**Example:**
|
|
1141
|
+
```typescript
|
|
1142
|
+
import { TS } from '@avstantso/ts';
|
|
1143
|
+
|
|
1144
|
+
type Empty = TS.String.Split<'', ASCII.Character>; // ['']
|
|
1145
|
+
type Pipe = TS.String.Split<'A|B', '|'>; // ['A', 'B']
|
|
1146
|
+
type NoMatch = TS.String.Split<'A|B', ','>; // ['A|B']
|
|
1147
|
+
type CSV = TS.String.Split<'First,Next', ','>; // ['First', 'Next']
|
|
1148
|
+
```
|
|
1149
|
+
|
|
963
1150
|
### String Manipulation Types
|
|
964
1151
|
|
|
965
1152
|
#### `TS.String.Repeat<S, N>`
|
package/dist/_global/string.d.ts
CHANGED
|
@@ -97,6 +97,31 @@ declare namespace AVStantso.TS.String {
|
|
|
97
97
|
* type l2 = CheckType<SplitToChars<'AB'>, ['A', 'B']>;
|
|
98
98
|
*/
|
|
99
99
|
export type SplitToChars<S extends string> = S extends undefined ? S : _SplitToChars<S>;
|
|
100
|
+
/**
|
|
101
|
+
* @summary Split `string` literal to substrings array by `Separator`.\
|
|
102
|
+
* ⚠ Unsafe, internal
|
|
103
|
+
* @example
|
|
104
|
+
* type n = CheckType<_Split<never, never>, never>;
|
|
105
|
+
* type u = CheckType<_Split<undefined, never>, [undefined]>; // ⚠
|
|
106
|
+
*
|
|
107
|
+
* type l0 = CheckType<_Split<'', ASCII.Character>, ['']>;
|
|
108
|
+
* type l1 = CheckType<_Split<'A|B', '|'>, ['A', 'B']>;
|
|
109
|
+
* type l2 = CheckType<_Split<'A|B', ','>, ['A|B']>;
|
|
110
|
+
* type l3 = CheckType<_Split<'First,Next', ','>, ['First', 'Next']>;
|
|
111
|
+
*/
|
|
112
|
+
export type _Split<S extends string, Separator extends ASCII.Character, R extends string[] = []> = S extends `${infer C}${Separator}${infer E}` ? _Split<E, Separator, [...R, C]> : [...R, S];
|
|
113
|
+
/**
|
|
114
|
+
* @summary Split `string` literal to substrings array by `Separator`
|
|
115
|
+
* @example
|
|
116
|
+
* type n = CheckType<Split<never, never>, never>;
|
|
117
|
+
* type u = CheckType<Split<undefined, never>, []>;
|
|
118
|
+
*
|
|
119
|
+
* type l0 = CheckType<Split<'', ASCII.Character>, ['']>;
|
|
120
|
+
* type l1 = CheckType<Split<'A|B', '|'>, ['A', 'B']>;
|
|
121
|
+
* type l2 = CheckType<Split<'A|B', ','>, ['A|B']>;
|
|
122
|
+
* type l3 = CheckType<Split<'First,Next', ','>, ['First', 'Next']>;
|
|
123
|
+
*/
|
|
124
|
+
export type Split<S extends string, Separator extends ASCII.Character> = S extends undefined ? S : Separator extends undefined ? Separator : _Split<S, Separator>;
|
|
100
125
|
type _Repeat<S extends Possible, N extends number, R extends string = ''> = N extends 0 ? R : _Repeat<S, Decrement<N>, `${R}${S}`>;
|
|
101
126
|
/**
|
|
102
127
|
* @summary Repeat string possible `S` by `N` times
|