String 要匹配标题大小写的TypeScript模板文字类型

String 要匹配标题大小写的TypeScript模板文字类型,string,typescript,template-literals,String,Typescript,Template Literals,我正在处理一个只匹配标题大小写字符串的模板文本类型。我想我应该首先使用大写字母创建一个单词匹配器: const uppercaseWord:Uppercase='U'; 但它似乎也匹配小写字母: const uppercaseWord:Uppercase='u'; 这个不会扔 我尝试过参数化它: type SingleUpperCase=`${Uppercase}`; const upperCaseWord:SingleUpperCase='U'; 但无法推断类型参数。它通过显式传递字符串

我正在处理一个只匹配标题大小写字符串的模板文本类型。我想我应该首先使用
大写字母
创建一个单词匹配器:

const uppercaseWord:Uppercase='U';
但它似乎也匹配小写字母:

const uppercaseWord:Uppercase='u';
这个不会扔

我尝试过参数化它:

type SingleUpperCase=`${Uppercase}`;
const upperCaseWord:SingleUpperCase='U';
但无法推断类型参数。它通过显式传递字符串文本来工作:

type SingleUpperCase=`${Uppercase}`;
const upperCaseWord:SingleUpperCase='U';
它是有效的,但我需要更通用的。匹配任何大写字符串的东西。如果我再次尝试将
string
作为类型参数传递,则错误已得到解决,但可以在不出错的情况下分配小写字母:

type SingleUpperCase=`${Uppercase}`;
const upperCaseWord:SingleUpperCase='u';//无误

我想知道这是否可能,因为它需要编译器提供类似regex的字符串匹配。

旁白:我不确定“标题大小写”有什么规则;我不知道
“HTML字符串”
是否在标题格中。对于下面的内容,我假设您只需要确保字符串的第一个字符和每个空格
(“”)
后面的第一个字符不是小写。这意味着
“HTML字符串”
可以。如果您有不同的规则,您可以调整下面答案中的代码


TypeScript中没有表示标题大小写为
string
s的特定类型。不要把这个给你;并且只产生
字符串
,因为没有更好的东西。对于真正的标题大小写
string
类型,正如您所说,您需要正则表达式验证
string
类型。在询问此类正则表达式验证类型的用例时存在一个开放性问题;如果下面的解决方案不能满足您的需求,那么您可能需要用您的用例来评论这个问题,为什么它是引人注目的,以及为什么替代解决方案不能满足您的需求


虽然这里没有特定的类型,但是您可以编写一个模板文本类型
TitleCase
,它可以用作
T
的约束。这意味着
T扩展TitleCase
当且仅当
T
是以标题为大小写的字符串

然后,为了避免人们不得不用某种泛型类型对字符串进行注释,您需要编写一个助手函数,如
asTitleCase()
,它只返回其输入,但如果传入错误字符串,则会产生编译器错误

因此,虽然您的理想解决方案如下所示:

/* THIS IS NOT POSSIBLE
const okay: TitleCase = "This Is Fine"; // okay
const error: TitleCase = "This is not fine"; // error
const alsoError: TitleCase = String(Math.random()); // error
*/
const okay = asTitleCase("This Is Fine"); // no error
const error = asTitleCase("This is not fine"); // error!
// ---------------------> ~~~~~~~~~~~~~~~~~~
// Argument of type '"This is not fine"' is not assignable to 
// parameter of type '"This Is Not Fine"'.

const alsoError = asTitleCase(String(Math.random())); // error!
// Argument of type 'string' is not assignable to parameter of type
// '"Please Use a Title Cased String Literal Here, Thx"'
可实施的解决方案如下所示:

/* THIS IS NOT POSSIBLE
const okay: TitleCase = "This Is Fine"; // okay
const error: TitleCase = "This is not fine"; // error
const alsoError: TitleCase = String(Math.random()); // error
*/
const okay = asTitleCase("This Is Fine"); // no error
const error = asTitleCase("This is not fine"); // error!
// ---------------------> ~~~~~~~~~~~~~~~~~~
// Argument of type '"This is not fine"' is not assignable to 
// parameter of type '"This Is Not Fine"'.

const alsoError = asTitleCase(String(Math.random())); // error!
// Argument of type 'string' is not assignable to parameter of type
// '"Please Use a Title Cased String Literal Here, Thx"'
同样,这是可以实现的,而不是理想的。所有使用标题大小写的字符串类型都需要获得一个额外的泛型类型参数

请注意,您可能不需要实际编写asTitleCase(…),除非您希望在声明处看到错误。大概您有一些函数(比如,
lookupBookTitle()
)关心标题大小写。如果是这样,您只需将该函数设置为泛型,并在那里强制执行约束。因此,不是
const str=asTitleCase(“XXX”);lookupBookTitle(str),您只需编写
const str=“XXX”;lookupBookTitle(str)唯一的区别是错误出现的位置

此外,在类似
lookupBookTitle()
的实现中,您可能只需要将输入扩展到
string
,并将其视为已验证。即使
T extends TitleCase
对调用方具有强制约束的效果,但当
T
是未指定的泛型类型参数时,编译器将无法遵循逻辑:

// callers see a function that constrains title to TitleCase
function lookupBookTitle<T extends string>(title: VerifyTitleCase<T>): Book;

// implementer just uses string
function lookupBookTitle(title: string) {  
  const book = db.lookupByTitle(title); 
  if (!book) throw new Error("NO BOOK");
  return book;
}
然后我们可以编写一个
VerifyTitleCase
类型来检查
T是否扩展TitleCase
。如果是,则解析为
T
。如果没有,它将解析为
标题库
,或者解析为一些硬编码的错误字符串,希望能让用户知道哪里出错了。(TypeScript中没有中要求的“
抛出
类型”或“
无效
类型”;因此使用硬编码错误字符串文字是一种解决方法):

type VerifyTitleCase=T扩展滴定酶?T:
滴定酶永不延伸?“请在此处使用标题大小写字符串文字,Thx”:
滴定酶
最后,助手函数:

const asTitleCase = <T extends string>(s: VerifyTitleCase<T>) => s;
const asTitleCase=(s:VerifyTitleCase)=>s;


很抱歉,问题描述太松散,我的意思是字符串中的每个单词都应该以大写字母开头,而对单词的其余部分没有限制。最终我需要的是编译时静态检查函数的字符串参数,您提出的解决方案可以完美地完成这项工作。
const asTitleCase = <T extends string>(s: VerifyTitleCase<T>) => s;