It can be difficult to work with the new TileMaps if you want to interact with many tiles within the same map in different ways.

I have figured out a way to get the layer on which a collision occurred between something like a CharacterBody2D and a TileMap.

First you get the TileMap (collider) and the RID. Then you can get the collision layer of the tile you collided with using PhysicsServer2D.body_get_collision_layer().

var collision = move_and_slide()
if collision:
    var collider = get_last_slide_collision().get_collider()

    if collider is TileMap:
        var tile_rid = get_last_slide_collision().get_collider_rid()
        layer_of_collision = PhysicsServer2D.body_get_collision_layer(tile_rid)

Save this in a variable with node-level scope at the top of your script (layer_of_collision). I have two tiles in my TileMap that I want special behavior for. I have given them each their own collision layer and declared constants for them:

const PLATFORM_LAYER = 1 << (2 - 1)    # collision layer 2
const ITEM_BLOCK_LAYER = 1 << (6 - 1)  # collision layer 6
var layer_of_collision = null

Now that you have the collision layer, you can use it to validate actions.

Example 1: Check if a player can crouch fall through the tile. Temporarily alter the player's collision mask and re-enable it after a short time.

if crouched and layer_of_collision == PLATFORM_LAYER:
    self.set_collision_mask_value(PLATFORM_LAYER, false)
    $FallTimer.start()
func _on_fall_timer_timeout():
    self.set_collision_mask_value(PLATFORM_LAYER, true)

Example 2: Change the tile of an item block the player has hit to a platform.

const TILE_LAYER = 0
const PLATFORM_TILE = Vector2i(0, 2)  # TileMap atlas coordinates for platform tile
if layer_of_collision == ITEM_BLOCK_LAYER:
    var tile_world_coords = collider.get_coords_for_body_rid(tile_rid)

    var tile_source_id = collider.get_cell_source_id(TILE_LAYER, tile_world_coords, false)
    if tile_source_id == -1:
        layer_of_collision = null
        return

    collider.set_cell(TILE_LAYER, tile_world_coords, tile_source_id, PLATFORM_TILE)

Example 3: Get custom data from the tile's custom data layer with the name "type".

Use some of the same code from Example 2, then:

const NULL_TILE = Vector2i(-1, -1)  # TileMap atlas coordinates for invalid tile
var tile_atlas_coords = collider.get_cell_atlas_coords(TILE_LAYER, tile_world_coords, false)
if tile_atlas_coords == NULL_TILE:
    layer_of_collision = null
    return

var tile_source = collider.tile_set.get_source(tile_source_id)
var tile_type = tile_source.get_tile_data(tile_atlas_coords, 0).get_custom_data("type")

Now you can use this data to take some other action.

Some of the included error checking may be unnecessary, but I left it in just in case.

I hope this information is useful for you.