Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
couchand opened this issue Mar 7, 2018 · 9 comments
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Help Wanted You can do this
Milestone

Comments

@couchand
Copy link

couchand commented Mar 7, 2018

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)

@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript Help Wanted You can do this Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript labels Mar 7, 2018
@RyanCavanaugh
Copy link
Member

We can collapse the two overloads in the ES5 lib file

@mhegazy mhegazy added this to the Community milestone Mar 7, 2018
@jbccollins
Copy link

Got any suggestions for a workaround in the meantime?

@couchand
Copy link
Author

@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);
}

@RyanCavanaugh RyanCavanaugh modified the milestones: Community, Backlog Mar 7, 2019
@alexandercerutti
Copy link

alexandercerutti commented May 11, 2019

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.

@cpplearner
Copy link

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

@alexandercerutti
Copy link

alexandercerutti commented May 11, 2019

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.

@bluelovers
Copy link
Contributor

bluelovers commented May 29, 2019

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

@santi020k
Copy link

I can solve this problem with toString()

newPath.replace([${item}], (router?.query?.[item ?? ''] ?? '')?.toString())

This is my code in case it works for someone, its a wor with with nextjs router

@ghost
Copy link

ghost commented Jul 21, 2022

return str.replace(new RegExp("foo"), replacer.toString());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Help Wanted You can do this
Projects
None yet
Development

No branches or pull requests

8 participants