Mutate across

library(tidyverse)
library(magrittr)
countries <- tibble(value = c(101, 102), labels = c('NL', 'BE'))
meta <- tibble(name = c("a", "b", "c"),
               type = c("int", "char", "factor"),
               levels = list(tibble(), tibble(), countries))
meta
## # A tibble: 3 x 3
##   name  type   levels          
##   <chr> <chr>  <list>          
## 1 a     int    <tibble [0 × 0]>
## 2 b     char   <tibble [0 × 0]>
## 3 c     factor <tibble [2 × 2]>
data <- tibble(a = c("1", "2", "3"),
               b = c("a", "b", "c"),
               c = c("101", "102", "102"))
data
## # A tibble: 3 x 3
##   a     b     c    
##   <chr> <chr> <chr>
## 1 1     a     101  
## 2 2     b     102  
## 3 3     c     102
my_cast <- function (column, colmeta) {
  if (nrow(colmeta$levels[[1]]) > 0) {
    factor(column, levels = colmeta$levels[[1]]$value)
  } else if (colmeta$type == 'int') {
    as.integer(column)
  } else if (colmeta$type == 'char') {
    as.character(column)
  }
}

data %<>% mutate(across(names(data), ~ my_cast(.x, filter(meta, name == cur_column()))))
data
## # A tibble: 3 x 3
##       a b     c    
##   <int> <chr> <fct>
## 1     1 a     101  
## 2     2 b     102  
## 3     3 c     102