If your object is a raster, then:
res(rasterObj)
gives you the resolution (vector, length 2, because you can have rasters in which the 2 dimensions are not of equal size)
In the LandWeb project, we use an input study area (called shpStudyRegionFull), which gives us the "Large Relevant Study Area", and a sub region of that (shpStudySubRegion) which we use during development, or for any time we only need a subset of the full area. Both of those are shapefiles, so as you say, do not have a resolution. We take initial *extent* from these two objects. The extents are actually not quite exact for a raster, and these actually get updated (see next paragraph).
There are MANY rasters used throughout the LandWeb project. The first one that is loaded, called biomassMap, is taken as the "canonical" raster. We crop and mask this file with the shpStudySubRegion as the "cookie cutter". From that point on, we use biomassMap resolution ( res(sim$biomassMap) ), coordinate reference system (crs(sim$biomassMap)), and we make a slight change to the study extent and bottom-left corner to match this biomassMap raster. Because a raster has a resolution, the extent that came from the shapefiles above will not match to the 250m x 250m resolution of the raster (it will be within 250m of that) because a shapefile can have real number coordinates, and thus real number extent.
For biomassMap and all the remaining rasters we load, we use prepInputs which can specify both
Cache(prepInputs, ...
studyArea = sim$shpStudySubRegion # used to mask, i.e,. put NA in all pixels outside of the sim$shpStudySubRegion cutline
rasterToMatch = sim$biomassMap # used for resolution, crs, extent
)
which will accomplish the above.