1

In .NET i can do:

var ls = new List<string>(1,2,3,3,3,4,5,6);

var x1 = ls.Single(x => x == 3); // throws exception because there are more elems of 3 defined in ls
var x2 = ls.SingleOrDefault(x => x==3) // Returns default of int (0) because there are more elems of 3 defined in ls
var x3 = ls.Single(x => x== 1) // returns 1

Single documentation:

https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.single?view=netcore-3.1

What would be the Typescript equivalent?

I'm working in the latest version of Angular.

3
  • 1
    Array#find() will give you a single item based on a predicate. If it nothing matches, you get undefined. It's basically .First(), since it doesn't fail with multiple matches. There is no direct equivalent for .Single() - you can use other libraries (some even add LINQ type methods in JS), or implement the functionality it yourself. Commented Jul 9, 2020 at 9:12
  • @VLAZ i see nothing baked in of the sorts. Welp if you could whip up a sample on how .Single or .SingleOrDefault would look like in .TS i would gladly accept the answer - .Ts is still foreign to me although i could make something myself i suppose. Commented Jul 9, 2020 at 9:15
  • 1
    Related: Angular 2 TypeScript how to find element in Array Commented Jul 9, 2020 at 17:16

2 Answers 2

1

That's not a TypeScript problem, rather a EcmaScript one: there's no a Linq-y set of extensions, but you can easily write a function like this one:

const ls = [1, 2, 3, 3, 3, 4, 5, 6];

function single<T>(a: ReadonlyArray<T>, fallback?: T): T {
    if (a.length === 1) return a[0];
    if (a.length === 0 && fallback !== void 0) return fallback;
    throw new Error();
}

// *** Single-like ***

const s1 = single(ls.filter(x => x === 1));  //found one
console.log(s1);  //outputs 1

const s2 = single(ls.filter(x => x === 9));  //found none => throws
const s3 = single(ls.filter(x => x === 3));  //found many => throws

// *** SingleOrDefault-like (just add a valid fallback) ***

const s4 = single(ls.filter(x => x === 1), 0);  //found one
console.log(s4);

const s5 = single(ls.filter(x => x === 9), 0);  //found none => fallback
console.log(s5);

const s6 = single(ls.filter(x => x === 3), 0);  //found many => throws

Also have a check at the Immutable.JS library, which has no single-facility, but is very close to the Linq schema.

Sign up to request clarification or add additional context in comments.

Comments

1

You will need to write such utility yourself, unfortunately. It could look something like:

const single = <T>(list: T[], predicate: (element: T) => boolean): T => {
  const index = list.findIndex(predicate);
  if (index === -1) throw new RangeError('No value found');

  const trimmedList: T[] = list.slice(index + 1);
  const nextIndex = trimmedList.findIndex(predicate);
  if (nextIndex !== -1) throw new RangeError('Multiple values found');

  return list[index];
};

const predicate = (value: number) => value === 1;

// These should then behave just like Single in .NET
single([1, 2, 3, 4], predicate); // Will return 1
single([1, 1, 2, 3, 4], predicate); // Will throw 'Multiple values found'
single([2, 3, 4], predicate); // Will throw 'No value found'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.