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

Template type fails to infer a match #48430

Closed
wbt opened this issue Mar 25, 2022 · 4 comments
Closed

Template type fails to infer a match #48430

wbt opened this issue Mar 25, 2022 · 4 comments

Comments

@wbt
Copy link

wbt commented Mar 25, 2022

Bug Report

πŸ”Ž Search Terms

Template literal type narrowing fails string 2345

πŸ•— Version & Regression Information

  • This changed between versions 4.0.5 and 4.1.5 because that is when the feature was introduced.

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

type EventName<T extends string> = `${T}Changed`; //From feature announcement: https://github.com/microsoft/TypeScript/pull/40336
const functionRequiresEventString = function(narrowedString: EventName<string>) {
	console.log('The following string is an event string per the original example: ' + narrowedString);
}
const nameEvent = function(whatChanged: string) {
	functionRequiresEventString('Functionality Changed');
	//Next line fails: Argument of type 'string' is not assignable to parameter of type '`${string}Changed`'.ts(2345)
	functionRequiresEventString(whatChanged + 'Changed');
}

πŸ™ Actual behavior

Error: Argument of type 'string' is not assignable to parameter of type '${string}Changed'.ts(2345) (but with backticks inside the quotes in the type).

πŸ™‚ Expected behavior

No error: The concatenated string ends in 'Changed' and should pass typechecking.

Related Issues

This is a minimal example using the first example of what should be supported, from the feature announcement, so I don't think reporting an issue in the announced functionality is a duplicate of this issue looking for gaps in what that didn't cover, and that thread is now being ignored anyway. This looks a lot like this issue reported 9/1/20 as a comment on the merged PR but is simpler than this issue around numbers. It’s also simpler than what this commenter sought around a fixed prefix.

@whzx5byb
Copy link

Concatenation with + won't produce a template literal type. You must use template strings like functionRequiresEventString(`${whatChanged}Changed`)

@wbt
Copy link
Author

wbt commented Mar 25, 2022

@whzx5byb Thanks for the helpful reply. I think it mainly calls out a shortcoming in the minimal example above.
A slightly more realistic case that can't be covered by that is here:

type EventName<T extends string> = `${T}Changed`; //From feature announcement: https://github.com/microsoft/TypeScript/pull/40336
const functionRequiresEventString = function(narrowedString: EventName<string>) {
	console.log('The following string is an event string per the original example: ' + narrowedString);
}
const ensureEventName = function(stringIn: string) : EventName<string> {
	if(stringIn.endsWith('Changed')) {
		return stringIn;
	} else {
		return `${stringIn}Changed`;
	}
}

On the line return stringIn there's an error that this variable isn't assignable to that narrower string type.

@whzx5byb
Copy link

whzx5byb commented Mar 25, 2022

@wbt

The return type of endsWith is not a type predicate, so it doesn't narrow type as you expected. Related: #46958

@wbt
Copy link
Author

wbt commented Mar 26, 2022

Thanks for the reply; this does look like it boils down to a combination of the comment above and #46958, both of which are unexpected. I'll use casting as a workaround.

@wbt wbt closed this as completed Mar 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants