summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md1
-rw-r--r--lib/pure/typetraits.nim12
-rw-r--r--tests/metatype/ttypetraits.nim20
3 files changed, 33 insertions, 0 deletions
diff --git a/changelog.md b/changelog.md
index abb761b4f..2c7cdeed0 100644
--- a/changelog.md
+++ b/changelog.md
@@ -114,6 +114,7 @@
 - Add `os.normalizeExe`, eg: `koch` => `./koch`.
 - `macros.newLit` now preserves named vs unnamed tuples; use `-d:nimHasWorkaround14720` to keep old behavior
 - Add `random.gauss`, that uses the ratio of uniforms method of sampling from a Gaussian distribution.
+- Add `typetraits.elementType` to get element type of an iterable.
 
 ## Language changes
 - In the newruntime it is now allowed to assign to the discriminator field
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index 317376405..346ac06d4 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -93,6 +93,18 @@ since (1, 1):
   type StaticParam*[value: static type] = object
     ## used to wrap a static value in `genericParams`
 
+since (1, 3, 5):
+  template elementType*(a: untyped): typedesc =
+    ## return element type of `a`, which can be any iterable (over which you
+    ## can iterate)
+    runnableExamples:
+      iterator myiter(n: int): auto =
+        for i in 0..<n: yield i
+      doAssert elementType(@[1,2]) is int
+      doAssert elementType("asdf") is char
+      doAssert elementType(myiter(3)) is int
+    typeof(block: (for ai in a: ai))
+
 import std/macros
 
 macro genericParamsImpl(T: typedesc): untyped =
diff --git a/tests/metatype/ttypetraits.nim b/tests/metatype/ttypetraits.nim
index eb2384afb..10aa7783d 100644
--- a/tests/metatype/ttypetraits.nim
+++ b/tests/metatype/ttypetraits.nim
@@ -231,3 +231,23 @@ block genericHead:
   type Bar = object
   doAssert not compiles(genericHead(Bar))
   # doAssert seq[int].genericHead is seq
+
+block: # elementType
+  iterator myiter(n: int): auto =
+    for i in 0..<n: yield i
+  iterator myiter3(): int = yield 10
+  iterator myiter2(n: int): auto {.closure.} =
+    for i in 0..<n: yield i
+  doAssert elementType(@[1,2]) is int
+  doAssert elementType("asdf") is char
+  doAssert elementType(myiter(3)) is int
+  doAssert elementType(myiter2(3)) is int
+  doAssert elementType([1.1]) is float
+  doAssert compiles elementType([1])
+  doAssert not compiles elementType(1)
+  doAssert compiles elementType(myiter3())
+  doAssert not compiles elementType(myiter3)
+  # check that it also works for 0-sized seq:
+  var a: seq[int]
+  doAssert elementType(a) is int
+  doAssert elementType(seq[char].default) is char