string module - smart 'template literal' return types
See original GitHub issue🚀 Feature request
Use string ‘template literal’ behavior for ‘smarter’ return types
Current Behavior
import { pipe } from 'fp-ts/function'
import { startsWith } from 'fp-ts/string'
import * as O from 'fp-ts/Option'
declare const el: '00' | '01' | '10'
const a = pipe(
el,
O.fromPredicate(startsWith('1')),
)
// a: Option<'00' | '01' | '10'>
Desired Behavior
// a: Option<'10'>
Suggested Solution
const startsWith = <S extends string, E extends string>(e: E) => (s: S):
s is S extends `${E}${infer _}` ? S : never => s.startsWith(e)
Similar improvements could be made to toUpperCase
, toLowerCase
, trim
, trimLeft
, trimRight
, isEmpty
, surround
, unsurround
, dropLeft
, dropRight
, head
, tail
, and init
size
and split
, lookup
, replaceAll
, lines
and unlines
can also be implemented, but they’re a bit more complicated (links from ts-toolbelt)
Who does this impact? Who is this for?
Users manipulating string literal types
Describe alternatives you’ve considered
Could be put into a separate module (maybe fp-ts-std? @samhh)
Additional context
It’s a bit tricky to decide how complicated these types can get - many of these can be implemented simply, but there are a few that are more complicated.
We could import ‘ts-toolbelt’, but I’m sure that would have package size implications, and it might not be worth the effort to maintain anything more than the simplest type definitions
Your environment
Software | Version(s) |
---|---|
fp-ts | 2.12 |
TypeScript | 4.6 |
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:6 (6 by maintainers)
I just meant whether to have a utility type like
StartsWith
or a more complex type predicate. To me,Json
is a ‘regular’ type whereasStartsWith
is a ‘utility’ type (asStartsWith<'one', 'two'>
isnever
).Either way, it’s definitely a refinement. 😃
Do you mean something like this?
imo that’s a bit harder to read. Is there a disadvantage to exporting the
StartsWith
type?Here’s what I’m thinking for a complete implementation of the new functions - how does that look?