Currently I am using the RegExp (?:\(\) => (.*)|return (.*);) for a custom nameof function that is called like this: nameof(() => myVariable). Depending on the execution though the lambda is transpiled into something that contains the return myVariable; part therefore I need an alternative branch looking for return.
The transpiled output will be of the form ()=>{cov_26zslv4jy3.f[9]++;cov_26zslv4jy3.s[38]++;return options.type;}.
Examples are the following:
// should return "foo"
() => foo
// should return "foo.bar"
() => foo.bar
// should return "options.type"
()=>{cov_26zslv4jy3.f[9]++;cov_26zslv4jy3.s[38]++;return options.type;}
My current RegExp works however it has two matching groups depending on the type of whether the lambda was transpiled or not. Is it possible to rewrite the expression such I have a single matching group which will contain the name?
For further details, I have attached the full code of my function:
const nameofValidator: RegExp = new RegExp(/(?:\(\) => (.*)|return (.*);)/);
/**
* Used to obtain the simple (unqualified) string name of a variable.
* #param lambda A lambda expression of the form `() => variable` which should be resolved.
*/
export function nameof<TAny>(lambda: () => TAny): string {
const stringifiedLambda: string = String(lambda);
const matches: RegExpExecArray | null = nameofValidator.exec(stringifiedLambda);
if (matches === null) {
throw new ArgumentException("Lambda expression must be of the form `() => variable'.", nameof(() => lambda));
}
if (matches[1] !== undefined) {
return matches[1];
}
if (matches[2] !== undefined) {
return matches[2];
}
throw new ArgumentException("Lambda expression must be of the form `() => variable'.", nameof(() => lambda));
}
You could use:
(?:\(\) =>|.*return) ([^;\r\n]*)
If first side of alternation is not found engine tries the second. If we know one condition should satisfy engine at any time, greedy dot .* will make it to happen earlier. You may need ^ anchor too.
Live demo
There is a second approach too:
\(\) *=>.* ([^;\r\n]+)
Related
There is a function that checks the content of the url with window.location.href. If the URL contains a specific string it should return true:
const doesItContain = () => {
const url = window.location.href;
return url.includes('/items');
};
This works fine, if the url contains /items it returns true. The issue comes when it needs to check for multiple strings (multiple pages) and return true if one of them are present. For example:
const doesItContain = () => {
const url = window.location.href;
return url.includes('/items', '/users');
};
It returns true only for the first string in the list. Is there a way to check for both or more than one string?
String.prototype.includes expects one argument. The other arguments are ignored.
You can use some to iterate an array of strings and check if at least one element fullfils the condition:
const doesItContain = () => {
const url = window.location.href;
return ['/items', '/users'].some(el => url.includes(el));
};
You can use a regular expression, separating each of the strings to check with |.
return /\/items|\/users/.test(url);
const example: (string: string) => string = string => {
return string.split("");
}
Its not a detailed question - I know, but I couldnt think of another way to ask and I simply do not understand what is happening in the below code.
I only understand only string as type is accepted, but how is this even a function -shouldnt it be:
const example = (string:string) => return string.split("")}
instead ?
Thanks!!
UPDATE:
There was some miscommunication maybe. I only want to understand the following (in bold letters):
const example**: (string: string) => string** = string => {
return string.split("");
}
why is it ":" and not "="?
what is: => string = string =>
why not just = string =>
?
Okay, actually there's a type error, it should be:
const example: (string: string) => string[] = string => {
return string.split("");
}
instead of (string: string) => string because string.split() will return an array.
also, it's better to rename the argument to something other than string as it can be easily confused with the type string.
Here's a fixed version:
const example: (someArg: string) => string[] = (someString) => {
return someString.split('');
};
So, the function example simply takes an argument (of type string) and returns an array of strings that is indicated by (string: string) => string[].
You can also use the below syntax if you find above a bit confusing:
const example2 = (someString: string): string[] => {
return someString.split('');
};
Update:
Considering this (string: string) => string,
why is it ":" and not "="?
It is not = because we're not yet assigning the value. We're still in the process of assigning the type. After giving the type, = is used to finally give it a value (which is an arrow function).
what is: => string = string => why not just = string => ?
TypeScript does understand that the returned value is an array of strings but => string[] is used to explicitly mention the return type (to make sure that the function always returns what we want it to return), we use => to separate the argument types and return type. Think of this as an arrow function like syntax for giving the type to a function.
This is the type:
vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
const example: (someArg: string) => string[] = (someString) => {
return someString.split('');
};
A function taking a string and returning a string.
Everything after the equals sign is the value.
You can use arrow function methodology in typescripts. It is a common way in most programming language for make more easy to read.
It is just a syntax. In background typescript will convert this method to vanilla function version.
your above code look like below code. There are many ways to write the same method different versions.
// you can write like this
function example( string: string ){
return string.split("");
}
// If you need to write multiple lines you should use circle brackets
const example = ( str : string ) => {
// do something here...
return str.split("");
}
// if you don't need to write multiple lines you can return like this.
const example = ( str : string ) => str.split("");
// But If you want to use return syntax. you can do. it is up to you.
const example = ( str : string ) => return str.split("");
If you give more detail. I can help you and apologize for my english.
If I misunderstand sorry about that.
Let's say I have
const highlight = (strings, ...values) => {
// console.logs in highlight
}
Let's say I want to create a "middleware" that modifies the template and then call highlight instead:
const doMore = (string, ...values) => {
// modify string/values and then call highlight here
}
So that I can now do something like
doMore`
the string ${template}
`;
I cannot figure out how to call highlight from doMore. How do I do this?
My first attempt was to use the ... operator. But this did not work. Specifically, I'm trying to create a wrapper for the npm chalk application, so I did something like:
const doMore = (string, ...values) => {
// extend string, values
return chalk(string, ...values)
}
but this throws an error: chalk_1.default.apply is not a function. Normally doing
chalk`the string ${template}`
but calling it using the spread operator is throwing this error.
You can use the ... spread syntax to convert an array into a list of arguments to call highlight:
const doMore = (string, ...values) => {
string += " foo";
values = values.map(v => v + " bar");
return highlight(string, ...values);
};
It looks like chalk_1.default.apply is an error from the transpiler that you are using rather than your code.
Here is an example of modifying the output from the tagged template literal.
const doMore = (template, ...values) => {
/**
* Make sure the template array is the same length as template.raw
*/
/** Add START on the first line. */
template[0] = "START" + template[0];
template.raw[0] = "START" + template.raw[0];
/** Add END on the last line. */
template[template.length - 1] =
template[template.length - 1] + "\nEND";
template.raw[template.raw.length - 1] =
template.raw[template.raw.length - 1] + "\\nEND";
return chalk(template, values);
};
console.log(doMore`
{red This text is shown in red.}
${"This text is inserted."}
{green This text is shown in green.}`);
Outputs:
START
This text is shown in red.
This text is inserted.
This text is shown in green.
END
So my question is how i can split the a string with backtick on each instance of variable.
I tried with \${.*?} but this will not work because ${variable} will be replaced by variable values first and than the split function will be executed.
Any idea how to do it ?
let a = 2
let b = 4
let x = `Superman${a}hello${b}one more`.split(/\${.*?}/g)
console.log(x)
On side not: I don't want a solution with wrapping it to " or '.
console.log('`Superman${a}hello${b}one more`'.split(/\${.*?}/g))
After the line executes, there is no way to get the original template string. However, you can use a tag function/tagged template literal to get the parts of the string, including the substitution values:
function Test() {
console.log(arguments)
return arguments.length - 1
}
let a = 2
let b = 4
let c = Test `Superman${a}hello${b}one more`
console.log(`This template string has ${c} substituted values`)
To clarify my comment to the original question here is an example of what the default Template Literal Function does:
function defaultTemplateLiteralFn(strs, ...args) {
return strs.map((str, idx) => str+(args[idx]||'')).join('');
}
const test = "special test";
const a = 10;
const b = 432;
console.log(`This is a ${test}. "${a}+${b}=${a+b}"`)
console.log(defaultTemplateLiteralFn`This is a ${test}. "${a}+${b}=${a+b}"`)
When you use a tagged template (IE: You don't provide a function to handle the template literal) The the language provides a default function that does something similar to what I do in my function defaultTemplateLiteralFn above. It returns the combined parts of the string with the values.
The example function takes each part of the string and puts the appropriate value after the string. If there is no value then it uses a blank string.
One way i have done is using template literal. i have seen this is being used in a in a library called styled-components which allows us to write css with js.
Would love to see other methods if there are any ?
function splitOnVariable(str, age){
// first argument to function will always be array of strings provided in input string.
return str
}
let a = 1;
let b = 2;
console.log(splitOnVariable`hello${a} break me on variable${b} !!!`)
Let say we want to fix text that was written on a AZERTY(or Dvorak, or another language layout) keyboard, as if it was a regular QWERTY one. We want to replace certain characters on corresponding ones.
So we have a dictionary, that looks similar to this:
const dic = {
q: a,
z: w,
}
But the dictionary is big, for every character. I'm searching for a way to do this not using for loops, using advantages of latest javascript changes, maybe with .replace() or .map() or anything you can suggest.
You don't need a big dictionary since a lot of the keys on AZERTY are in the same place: only make a map for the keys that are different and return the input if no mapping exists:
const dict = {
q: "a",
w: "z"
// e, r, t, y are in the same place, for example...
};
console.log(
"qwerty".split("") // Explode the string to an array
.map(letter => dict[letter] || letter) // Map inputs
.join("") // output a string
);
// Generate a reverse mapping
const reverse_dict = {};
Object.keys(dict).forEach(key => reverse_dict[dict[key]] = key);
console.log(
"azerty".split("")
.map(letter => reverse_dict[letter] || letter)
.join("")
);
Note that with arrow functions:
You do not need parenthesis around the parameter list if there is only one parameter.
If you omit the {} around the function body, you can also omit the return keyword and the body will return the value of the last (only) expression (save for a void parameter, which is a set of empty brackets () which you'll see in places like setTimeout).
A common misconception about const is that you can't update an array or object after it's initialized, but that's not the case. What you can't do is assign the variable to something else (like const o = {}; o = "")