Reputation: 14707
How do I ensure that my string have two words in it using typescript.
The reason I need this so that I would call server only if name is in "first last" name format.
Upvotes: 0
Views: 1453
Reputation: 106780
You can ensure your string has two words in it possibly containing letters with accents, multiple hyphens within, multiple apostrophes within, and separated by a space with RegEx.
const allowedChars = "a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; // https://stackoverflow.com/a/1073545/188246
const isTwoWordNameRegEx = new RegExp(`^[${allowedChars}]+(['\-][${allowedChars}]+)* [${allowedChars}]+(['\-][${allowedChars}]+)*$`, "i");
isTwoWordNameRegEx.test("Sébastien Doe"); // true
isTwoWordNameRegEx.test("John Doe"); // true
isTwoWordNameRegEx.test("John Doe-Williams") // true
isTwoWordNameRegEx.test("Scarlett O'Hara") // true
isTwoWordNameRegEx.test("John Doe-Williams-Jane") // true
isTwoWordNameRegEx.test("John Doe-") // false
isTwoWordNameRegEx.test("John Doe'") // false
isTwoWordNameRegEx.test("John' Doe") // false
isTwoWordNameRegEx.test("John Doe Williams") // false
Now that I've mentioned this... don't do it! It's still making an assumption about how a name might be. Please read Falsehoods Programmers Believe About Names.
If you really want to restrict it to two words, then please consider a very relaxed version:
const isTwoWordNameRegEx = /^\S+ \S+$/;
Upvotes: 0
Reputation: 13240
Things like this can't be typed with TypeScript, but you can make use of type guards to explicitly indicate that a param value needs to pass a specific test first to be a valid input to a function.
Here's what a "strongly typed" version of Scott's answer could be:
my-custom-types.d.ts
// A string supertype that represents a string that passed our RegEx test
declare type TwoWords = Branded<string, 'two-words'>
// Used to declare an unique primitive type, "nominal types" aren't supported yet
// @see https://github.com/Microsoft/TypeScript/issues/202
declare type Branded<T, U> = T & { '__brand': U }
// FullName in a "first last" name format
declare type FullName = TwoWords
my-test.ts
// This a type guard that casts strings with two words to TwoWords
function isTwoWords(input: string): input is TwoWords {
return /^[A-Za-z]+ [A-Za-z]+$/.test(input)
}
// This is the function that should only receive strings with two words
function showName(name: FullName) {
let [first, last] = name.split(' ') // Can be splited with safety
console.log(`${last}, ${first}`)
}
let name1 = 'John'
let name2 = 'John Doe'
let name3 = 'John Doe Junior'
// Error, you can't assume this string has two words before testing it
showName(name2)
for (let name of [name1, name2, name3]) {
if (isTwoWords(name)) {
// No errors, TS knows that only a TwoWords type reach this line
showName(name)
}
}
Upvotes: 0
Reputation: 65835
The answer really isn't TypeScript dependent. It's basic JavaScript.
You can use a regular expression to perform a test on the string:
function testString(input){
// Return whether or not there are letters (any amount and any case)
// followed by one space and then more letters (any amount and any case).
// Of course, if you wanted to get more specific about case or character
// counts, adjusting the regular expression would be simple.
return /^[A-Za-z]+ [A-Za-z]+$/.test(input);
}
console.log(testString("Scott"));
console.log(testString("Scott Marcus"));
console.log(testString("Scott\nMarcus"));
Upvotes: 4