Typescript: String.replace does not accept string | (string, ...any[]) => string replacer

Created on 7 Mar 2018  路  7Comments  路  Source: microsoft/TypeScript

TypeScript Version: 2.7.2

Search Terms: String.replace overload union parameter

Code

type ReplacerFn = () => string;
type Replacer = string | ReplacerFn;

function replaceFoo(str: string, replacer: Replacer) {
    return str.replace(new RegExp("foo"), replacer);
}

Expected behavior:
Compiles successfully.

Perhaps the change is as simple as combining the two overloads into a union, though the implications of that change are possibly unpleasant as far as tooling is concerned.

Actual behavior:
bad.ts(5,43): error TS2345: Argument of type 'Replacer' is not assignable to parameter of type '(substring: string, ...args: any[]) => string'. Type 'string' is not assignable to type '(substring: string, ...args: any[]) => string'.

Playground Link: playground link

Related Issues:

20432 (Array.from)

20215 (new Date)

14107 (underlying issue)

Bug lib.d.ts help wanted

Most helpful comment

@jbccollins in our codebase we currently use something like this very ugly snippet:

if (typeof replacer === 'string') {
    return str.replace(new RegExp("foo"), replacer);
}
else {
    return str.replace(new RegExp("foo"), replacer);
}

All 7 comments

We can collapse the two overloads in the ES5 lib file

Got any suggestions for a workaround in the meantime?

@jbccollins in our codebase we currently use something like this very ugly snippet:

if (typeof replacer === 'string') {
    return str.replace(new RegExp("foo"), replacer);
}
else {
    return str.replace(new RegExp("foo"), replacer);
}

Any news? I've experienced the same issue with the latest Typescript release.

I get the error with the second regex.

Object.keys(lang).map(key => `"${key}" = "${lang[key].replace(/"/g, /\\"/)}";`);

EDIT: My bad.

@alexandercerutti Passing regex as the second argument to replace is obviously a type mismatch. You probably want to use a string.

Holy shit. I was really convinced it was valid and it seemed to work. 馃槖 (but it does not make sense)
That's why I'm moving to Typescript.
Thank you very much @cpplearner.

export interface IRegExpCallback
{
    ($0: string, $1?: string, $2?: string, $3?: string, ...argv: string[]): string;
    (substring: string, ...args: any[]): string
}

export interface I1
{
    s: string | RegExp;
    r: string | IRegExpCallback
}

let d: I1 = {} as any;

''.replace(d.s, d.r)

Error: TS2345: Argument of type 'string | IRegExpCallback' is not assignable to parameter of type '(substring: string, ...args: any[]) => string'.
Type 'string' is not assignable to type '(substring: string, ...args: any[]) => string'.


''.replace(d.s, d.r as string)
''.replace(d.s, d.r as IRegExpCallback)

no error


''.replace(d.s, d.r);
''.replace(d.s, d.r as IRegExpCallback);
''.replace(d.s, d.r as string);

replace('', d.s, d.r);
replace('', d.s, d.r as IRegExpCallback);
replace('', d.s, d.r as string);

function replace(s: string, searchValue: string | RegExp, replaceValue: string): string
function replace(s: string, searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string
function replace(s: string, searchValue: string | RegExp, replacer: string | ((substring: string, ...args: any[]) => string)): string
{
    // @ts-ignore
    return null;
}

look like we need a realy or, because typescript try check all

Was this page helpful?
0 / 5 - 0 ratings

Related issues

manekinekko picture manekinekko  路  3Comments

CyrusNajmabadi picture CyrusNajmabadi  路  3Comments

blendsdk picture blendsdk  路  3Comments

wmaurer picture wmaurer  路  3Comments

zhuravlikjb picture zhuravlikjb  路  3Comments